commit d3bac575d42b7f003ca199cb59e64685b110c597 Author: Rumps Date: Fri Apr 14 08:29:38 2017 +0100 Initial commit diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..a6d4eb5 --- /dev/null +++ b/README.txt @@ -0,0 +1 @@ +Visit http://www.lancaster.ac.uk/ug/goldswor/scc300/ for webpage. \ No newline at end of file diff --git a/dat/archives/difffile-html.bz2 b/dat/archives/difffile-html.bz2 new file mode 100644 index 0000000..12aff56 Binary files /dev/null and b/dat/archives/difffile-html.bz2 differ diff --git a/dat/archives/difffile-images.bz2 b/dat/archives/difffile-images.bz2 new file mode 100644 index 0000000..fbfca6a Binary files /dev/null and b/dat/archives/difffile-images.bz2 differ diff --git a/dat/archives/difffile-large.bz2 b/dat/archives/difffile-large.bz2 new file mode 100644 index 0000000..d3eddfa Binary files /dev/null and b/dat/archives/difffile-large.bz2 differ diff --git a/dat/archives/difffile-small.bz2 b/dat/archives/difffile-small.bz2 new file mode 100644 index 0000000..2f6d565 Binary files /dev/null and b/dat/archives/difffile-small.bz2 differ diff --git a/dat/archives/difffile.bz2 b/dat/archives/difffile.bz2 new file mode 100644 index 0000000..5cec74e Binary files /dev/null and b/dat/archives/difffile.bz2 differ diff --git a/dat/archives/samefile-html.bz2 b/dat/archives/samefile-html.bz2 new file mode 100644 index 0000000..d50e0fd Binary files /dev/null and b/dat/archives/samefile-html.bz2 differ diff --git a/dat/archives/samefile-images.bz2 b/dat/archives/samefile-images.bz2 new file mode 100644 index 0000000..d0efe3a Binary files /dev/null and b/dat/archives/samefile-images.bz2 differ diff --git a/dat/cache/CacheHandlerBase.dn b/dat/cache/CacheHandlerBase.dn new file mode 100644 index 0000000..63bffc2 --- /dev/null +++ b/dat/cache/CacheHandlerBase.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/Thumbs.db b/dat/cache/Thumbs.db new file mode 100644 index 0000000..d91ff9e Binary files /dev/null and b/dat/cache/Thumbs.db differ diff --git a/dat/cache/difffile-large/0/CacheHandler0_0.dn b/dat/cache/difffile-large/0/CacheHandler0_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_1.dn b/dat/cache/difffile-large/0/CacheHandler0_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_10.dn b/dat/cache/difffile-large/0/CacheHandler0_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_11.dn b/dat/cache/difffile-large/0/CacheHandler0_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_12.dn b/dat/cache/difffile-large/0/CacheHandler0_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_13.dn b/dat/cache/difffile-large/0/CacheHandler0_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_14.dn b/dat/cache/difffile-large/0/CacheHandler0_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_15.dn b/dat/cache/difffile-large/0/CacheHandler0_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_16.dn b/dat/cache/difffile-large/0/CacheHandler0_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_17.dn b/dat/cache/difffile-large/0/CacheHandler0_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_18.dn b/dat/cache/difffile-large/0/CacheHandler0_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_19.dn b/dat/cache/difffile-large/0/CacheHandler0_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_2.dn b/dat/cache/difffile-large/0/CacheHandler0_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_20.dn b/dat/cache/difffile-large/0/CacheHandler0_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_21.dn b/dat/cache/difffile-large/0/CacheHandler0_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_22.dn b/dat/cache/difffile-large/0/CacheHandler0_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_23.dn b/dat/cache/difffile-large/0/CacheHandler0_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_24.dn b/dat/cache/difffile-large/0/CacheHandler0_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_25.dn b/dat/cache/difffile-large/0/CacheHandler0_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_26.dn b/dat/cache/difffile-large/0/CacheHandler0_26.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_27.dn b/dat/cache/difffile-large/0/CacheHandler0_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_28.dn b/dat/cache/difffile-large/0/CacheHandler0_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_29.dn b/dat/cache/difffile-large/0/CacheHandler0_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_3.dn b/dat/cache/difffile-large/0/CacheHandler0_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_30.dn b/dat/cache/difffile-large/0/CacheHandler0_30.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_31.dn b/dat/cache/difffile-large/0/CacheHandler0_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_32.dn b/dat/cache/difffile-large/0/CacheHandler0_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_33.dn b/dat/cache/difffile-large/0/CacheHandler0_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_34.dn b/dat/cache/difffile-large/0/CacheHandler0_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_4.dn b/dat/cache/difffile-large/0/CacheHandler0_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_5.dn b/dat/cache/difffile-large/0/CacheHandler0_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_6.dn b/dat/cache/difffile-large/0/CacheHandler0_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_7.dn b/dat/cache/difffile-large/0/CacheHandler0_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_8.dn b/dat/cache/difffile-large/0/CacheHandler0_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/0/CacheHandler0_9.dn b/dat/cache/difffile-large/0/CacheHandler0_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/0/CacheHandler0_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_0.dn b/dat/cache/difffile-large/1/CacheHandler1_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_1.dn b/dat/cache/difffile-large/1/CacheHandler1_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_10.dn b/dat/cache/difffile-large/1/CacheHandler1_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_11.dn b/dat/cache/difffile-large/1/CacheHandler1_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_12.dn b/dat/cache/difffile-large/1/CacheHandler1_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_13.dn b/dat/cache/difffile-large/1/CacheHandler1_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_14.dn b/dat/cache/difffile-large/1/CacheHandler1_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_15.dn b/dat/cache/difffile-large/1/CacheHandler1_15.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_16.dn b/dat/cache/difffile-large/1/CacheHandler1_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_17.dn b/dat/cache/difffile-large/1/CacheHandler1_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_18.dn b/dat/cache/difffile-large/1/CacheHandler1_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_19.dn b/dat/cache/difffile-large/1/CacheHandler1_19.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_2.dn b/dat/cache/difffile-large/1/CacheHandler1_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_20.dn b/dat/cache/difffile-large/1/CacheHandler1_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_21.dn b/dat/cache/difffile-large/1/CacheHandler1_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_22.dn b/dat/cache/difffile-large/1/CacheHandler1_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_23.dn b/dat/cache/difffile-large/1/CacheHandler1_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_24.dn b/dat/cache/difffile-large/1/CacheHandler1_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_25.dn b/dat/cache/difffile-large/1/CacheHandler1_25.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_26.dn b/dat/cache/difffile-large/1/CacheHandler1_26.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_27.dn b/dat/cache/difffile-large/1/CacheHandler1_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_28.dn b/dat/cache/difffile-large/1/CacheHandler1_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_29.dn b/dat/cache/difffile-large/1/CacheHandler1_29.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_3.dn b/dat/cache/difffile-large/1/CacheHandler1_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_30.dn b/dat/cache/difffile-large/1/CacheHandler1_30.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_31.dn b/dat/cache/difffile-large/1/CacheHandler1_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_32.dn b/dat/cache/difffile-large/1/CacheHandler1_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_33.dn b/dat/cache/difffile-large/1/CacheHandler1_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_34.dn b/dat/cache/difffile-large/1/CacheHandler1_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_4.dn b/dat/cache/difffile-large/1/CacheHandler1_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_5.dn b/dat/cache/difffile-large/1/CacheHandler1_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_6.dn b/dat/cache/difffile-large/1/CacheHandler1_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_7.dn b/dat/cache/difffile-large/1/CacheHandler1_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_8.dn b/dat/cache/difffile-large/1/CacheHandler1_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/1/CacheHandler1_9.dn b/dat/cache/difffile-large/1/CacheHandler1_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/1/CacheHandler1_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_0.dn b/dat/cache/difffile-large/10/CacheHandler10_0.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_1.dn b/dat/cache/difffile-large/10/CacheHandler10_1.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_10.dn b/dat/cache/difffile-large/10/CacheHandler10_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_11.dn b/dat/cache/difffile-large/10/CacheHandler10_11.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_12.dn b/dat/cache/difffile-large/10/CacheHandler10_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_13.dn b/dat/cache/difffile-large/10/CacheHandler10_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_14.dn b/dat/cache/difffile-large/10/CacheHandler10_14.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_15.dn b/dat/cache/difffile-large/10/CacheHandler10_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_16.dn b/dat/cache/difffile-large/10/CacheHandler10_16.dn new file mode 100644 index 0000000..8ed43fc --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/19 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_17.dn b/dat/cache/difffile-large/10/CacheHandler10_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_18.dn b/dat/cache/difffile-large/10/CacheHandler10_18.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_19.dn b/dat/cache/difffile-large/10/CacheHandler10_19.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_2.dn b/dat/cache/difffile-large/10/CacheHandler10_2.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_20.dn b/dat/cache/difffile-large/10/CacheHandler10_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_21.dn b/dat/cache/difffile-large/10/CacheHandler10_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_22.dn b/dat/cache/difffile-large/10/CacheHandler10_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_23.dn b/dat/cache/difffile-large/10/CacheHandler10_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_24.dn b/dat/cache/difffile-large/10/CacheHandler10_24.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_25.dn b/dat/cache/difffile-large/10/CacheHandler10_25.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_26.dn b/dat/cache/difffile-large/10/CacheHandler10_26.dn new file mode 100644 index 0000000..0726947 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_27.dn b/dat/cache/difffile-large/10/CacheHandler10_27.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_28.dn b/dat/cache/difffile-large/10/CacheHandler10_28.dn new file mode 100644 index 0000000..fd826ac --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_29.dn b/dat/cache/difffile-large/10/CacheHandler10_29.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_3.dn b/dat/cache/difffile-large/10/CacheHandler10_3.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_30.dn b/dat/cache/difffile-large/10/CacheHandler10_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_31.dn b/dat/cache/difffile-large/10/CacheHandler10_31.dn new file mode 100644 index 0000000..88d4397 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_32.dn b/dat/cache/difffile-large/10/CacheHandler10_32.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_33.dn b/dat/cache/difffile-large/10/CacheHandler10_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_34.dn b/dat/cache/difffile-large/10/CacheHandler10_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_4.dn b/dat/cache/difffile-large/10/CacheHandler10_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_5.dn b/dat/cache/difffile-large/10/CacheHandler10_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_6.dn b/dat/cache/difffile-large/10/CacheHandler10_6.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_7.dn b/dat/cache/difffile-large/10/CacheHandler10_7.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_8.dn b/dat/cache/difffile-large/10/CacheHandler10_8.dn new file mode 100644 index 0000000..07667c8 --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/10/CacheHandler10_9.dn b/dat/cache/difffile-large/10/CacheHandler10_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/10/CacheHandler10_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_0.dn b/dat/cache/difffile-large/11/CacheHandler11_0.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_1.dn b/dat/cache/difffile-large/11/CacheHandler11_1.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_10.dn b/dat/cache/difffile-large/11/CacheHandler11_10.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_11.dn b/dat/cache/difffile-large/11/CacheHandler11_11.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_12.dn b/dat/cache/difffile-large/11/CacheHandler11_12.dn new file mode 100644 index 0000000..07667c8 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_13.dn b/dat/cache/difffile-large/11/CacheHandler11_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_14.dn b/dat/cache/difffile-large/11/CacheHandler11_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_15.dn b/dat/cache/difffile-large/11/CacheHandler11_15.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_16.dn b/dat/cache/difffile-large/11/CacheHandler11_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_17.dn b/dat/cache/difffile-large/11/CacheHandler11_17.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_18.dn b/dat/cache/difffile-large/11/CacheHandler11_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_19.dn b/dat/cache/difffile-large/11/CacheHandler11_19.dn new file mode 100644 index 0000000..8ed43fc --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/19 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_2.dn b/dat/cache/difffile-large/11/CacheHandler11_2.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_20.dn b/dat/cache/difffile-large/11/CacheHandler11_20.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_21.dn b/dat/cache/difffile-large/11/CacheHandler11_21.dn new file mode 100644 index 0000000..b5d7024 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_22.dn b/dat/cache/difffile-large/11/CacheHandler11_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_23.dn b/dat/cache/difffile-large/11/CacheHandler11_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_24.dn b/dat/cache/difffile-large/11/CacheHandler11_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_25.dn b/dat/cache/difffile-large/11/CacheHandler11_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_26.dn b/dat/cache/difffile-large/11/CacheHandler11_26.dn new file mode 100644 index 0000000..dea93f4 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_27.dn b/dat/cache/difffile-large/11/CacheHandler11_27.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_28.dn b/dat/cache/difffile-large/11/CacheHandler11_28.dn new file mode 100644 index 0000000..fd826ac --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_29.dn b/dat/cache/difffile-large/11/CacheHandler11_29.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_3.dn b/dat/cache/difffile-large/11/CacheHandler11_3.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_30.dn b/dat/cache/difffile-large/11/CacheHandler11_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_31.dn b/dat/cache/difffile-large/11/CacheHandler11_31.dn new file mode 100644 index 0000000..88d4397 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_32.dn b/dat/cache/difffile-large/11/CacheHandler11_32.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_33.dn b/dat/cache/difffile-large/11/CacheHandler11_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_34.dn b/dat/cache/difffile-large/11/CacheHandler11_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_4.dn b/dat/cache/difffile-large/11/CacheHandler11_4.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_5.dn b/dat/cache/difffile-large/11/CacheHandler11_5.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_6.dn b/dat/cache/difffile-large/11/CacheHandler11_6.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_7.dn b/dat/cache/difffile-large/11/CacheHandler11_7.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_8.dn b/dat/cache/difffile-large/11/CacheHandler11_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/11/CacheHandler11_9.dn b/dat/cache/difffile-large/11/CacheHandler11_9.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/11/CacheHandler11_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_0.dn b/dat/cache/difffile-large/12/CacheHandler12_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_1.dn b/dat/cache/difffile-large/12/CacheHandler12_1.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_10.dn b/dat/cache/difffile-large/12/CacheHandler12_10.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_11.dn b/dat/cache/difffile-large/12/CacheHandler12_11.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_12.dn b/dat/cache/difffile-large/12/CacheHandler12_12.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_13.dn b/dat/cache/difffile-large/12/CacheHandler12_13.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_14.dn b/dat/cache/difffile-large/12/CacheHandler12_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_15.dn b/dat/cache/difffile-large/12/CacheHandler12_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_16.dn b/dat/cache/difffile-large/12/CacheHandler12_16.dn new file mode 100644 index 0000000..451c75e --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 14-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_17.dn b/dat/cache/difffile-large/12/CacheHandler12_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_18.dn b/dat/cache/difffile-large/12/CacheHandler12_18.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_19.dn b/dat/cache/difffile-large/12/CacheHandler12_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_2.dn b/dat/cache/difffile-large/12/CacheHandler12_2.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_20.dn b/dat/cache/difffile-large/12/CacheHandler12_20.dn new file mode 100644 index 0000000..9334046 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*13 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_21.dn b/dat/cache/difffile-large/12/CacheHandler12_21.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_22.dn b/dat/cache/difffile-large/12/CacheHandler12_22.dn new file mode 100644 index 0000000..b5d7024 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_23.dn b/dat/cache/difffile-large/12/CacheHandler12_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_24.dn b/dat/cache/difffile-large/12/CacheHandler12_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_25.dn b/dat/cache/difffile-large/12/CacheHandler12_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_26.dn b/dat/cache/difffile-large/12/CacheHandler12_26.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_27.dn b/dat/cache/difffile-large/12/CacheHandler12_27.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_28.dn b/dat/cache/difffile-large/12/CacheHandler12_28.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_29.dn b/dat/cache/difffile-large/12/CacheHandler12_29.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_3.dn b/dat/cache/difffile-large/12/CacheHandler12_3.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_30.dn b/dat/cache/difffile-large/12/CacheHandler12_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_31.dn b/dat/cache/difffile-large/12/CacheHandler12_31.dn new file mode 100644 index 0000000..fcc56ef --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 11/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_32.dn b/dat/cache/difffile-large/12/CacheHandler12_32.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_33.dn b/dat/cache/difffile-large/12/CacheHandler12_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_34.dn b/dat/cache/difffile-large/12/CacheHandler12_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_4.dn b/dat/cache/difffile-large/12/CacheHandler12_4.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_5.dn b/dat/cache/difffile-large/12/CacheHandler12_5.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_6.dn b/dat/cache/difffile-large/12/CacheHandler12_6.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_7.dn b/dat/cache/difffile-large/12/CacheHandler12_7.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_8.dn b/dat/cache/difffile-large/12/CacheHandler12_8.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/12/CacheHandler12_9.dn b/dat/cache/difffile-large/12/CacheHandler12_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/12/CacheHandler12_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_0.dn b/dat/cache/difffile-large/13/CacheHandler13_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_1.dn b/dat/cache/difffile-large/13/CacheHandler13_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_10.dn b/dat/cache/difffile-large/13/CacheHandler13_10.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_11.dn b/dat/cache/difffile-large/13/CacheHandler13_11.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_12.dn b/dat/cache/difffile-large/13/CacheHandler13_12.dn new file mode 100644 index 0000000..0f6afab --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_13.dn b/dat/cache/difffile-large/13/CacheHandler13_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_14.dn b/dat/cache/difffile-large/13/CacheHandler13_14.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_15.dn b/dat/cache/difffile-large/13/CacheHandler13_15.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_16.dn b/dat/cache/difffile-large/13/CacheHandler13_16.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_17.dn b/dat/cache/difffile-large/13/CacheHandler13_17.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_18.dn b/dat/cache/difffile-large/13/CacheHandler13_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_19.dn b/dat/cache/difffile-large/13/CacheHandler13_19.dn new file mode 100644 index 0000000..451c75e --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 14-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_2.dn b/dat/cache/difffile-large/13/CacheHandler13_2.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_20.dn b/dat/cache/difffile-large/13/CacheHandler13_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_21.dn b/dat/cache/difffile-large/13/CacheHandler13_21.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_22.dn b/dat/cache/difffile-large/13/CacheHandler13_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_23.dn b/dat/cache/difffile-large/13/CacheHandler13_23.dn new file mode 100644 index 0000000..9334046 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*13 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_24.dn b/dat/cache/difffile-large/13/CacheHandler13_24.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_25.dn b/dat/cache/difffile-large/13/CacheHandler13_25.dn new file mode 100644 index 0000000..b5d7024 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_26.dn b/dat/cache/difffile-large/13/CacheHandler13_26.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_27.dn b/dat/cache/difffile-large/13/CacheHandler13_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_28.dn b/dat/cache/difffile-large/13/CacheHandler13_28.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_29.dn b/dat/cache/difffile-large/13/CacheHandler13_29.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_3.dn b/dat/cache/difffile-large/13/CacheHandler13_3.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_30.dn b/dat/cache/difffile-large/13/CacheHandler13_30.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_31.dn b/dat/cache/difffile-large/13/CacheHandler13_31.dn new file mode 100644 index 0000000..fcc56ef --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 11/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_32.dn b/dat/cache/difffile-large/13/CacheHandler13_32.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_33.dn b/dat/cache/difffile-large/13/CacheHandler13_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_34.dn b/dat/cache/difffile-large/13/CacheHandler13_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_4.dn b/dat/cache/difffile-large/13/CacheHandler13_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_5.dn b/dat/cache/difffile-large/13/CacheHandler13_5.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_6.dn b/dat/cache/difffile-large/13/CacheHandler13_6.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_7.dn b/dat/cache/difffile-large/13/CacheHandler13_7.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_8.dn b/dat/cache/difffile-large/13/CacheHandler13_8.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/13/CacheHandler13_9.dn b/dat/cache/difffile-large/13/CacheHandler13_9.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/13/CacheHandler13_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_0.dn b/dat/cache/difffile-large/14/CacheHandler14_0.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_1.dn b/dat/cache/difffile-large/14/CacheHandler14_1.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_10.dn b/dat/cache/difffile-large/14/CacheHandler14_10.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_11.dn b/dat/cache/difffile-large/14/CacheHandler14_11.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_12.dn b/dat/cache/difffile-large/14/CacheHandler14_12.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_13.dn b/dat/cache/difffile-large/14/CacheHandler14_13.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_14.dn b/dat/cache/difffile-large/14/CacheHandler14_14.dn new file mode 100644 index 0000000..0f6afab --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_15.dn b/dat/cache/difffile-large/14/CacheHandler14_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_16.dn b/dat/cache/difffile-large/14/CacheHandler14_16.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_17.dn b/dat/cache/difffile-large/14/CacheHandler14_17.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_18.dn b/dat/cache/difffile-large/14/CacheHandler14_18.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_19.dn b/dat/cache/difffile-large/14/CacheHandler14_19.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_2.dn b/dat/cache/difffile-large/14/CacheHandler14_2.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_20.dn b/dat/cache/difffile-large/14/CacheHandler14_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_21.dn b/dat/cache/difffile-large/14/CacheHandler14_21.dn new file mode 100644 index 0000000..451c75e --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 14-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_22.dn b/dat/cache/difffile-large/14/CacheHandler14_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_23.dn b/dat/cache/difffile-large/14/CacheHandler14_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_24.dn b/dat/cache/difffile-large/14/CacheHandler14_24.dn new file mode 100644 index 0000000..9334046 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*13 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_25.dn b/dat/cache/difffile-large/14/CacheHandler14_25.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_26.dn b/dat/cache/difffile-large/14/CacheHandler14_26.dn new file mode 100644 index 0000000..b5d7024 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_27.dn b/dat/cache/difffile-large/14/CacheHandler14_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_28.dn b/dat/cache/difffile-large/14/CacheHandler14_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_29.dn b/dat/cache/difffile-large/14/CacheHandler14_29.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_3.dn b/dat/cache/difffile-large/14/CacheHandler14_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_30.dn b/dat/cache/difffile-large/14/CacheHandler14_30.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_31.dn b/dat/cache/difffile-large/14/CacheHandler14_31.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_32.dn b/dat/cache/difffile-large/14/CacheHandler14_32.dn new file mode 100644 index 0000000..fcc56ef --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 11/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_33.dn b/dat/cache/difffile-large/14/CacheHandler14_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_34.dn b/dat/cache/difffile-large/14/CacheHandler14_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_4.dn b/dat/cache/difffile-large/14/CacheHandler14_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_5.dn b/dat/cache/difffile-large/14/CacheHandler14_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_6.dn b/dat/cache/difffile-large/14/CacheHandler14_6.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_7.dn b/dat/cache/difffile-large/14/CacheHandler14_7.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_8.dn b/dat/cache/difffile-large/14/CacheHandler14_8.dn new file mode 100644 index 0000000..04b26cb --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 8+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/14/CacheHandler14_9.dn b/dat/cache/difffile-large/14/CacheHandler14_9.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/14/CacheHandler14_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_0.dn b/dat/cache/difffile-large/15/CacheHandler15_0.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_1.dn b/dat/cache/difffile-large/15/CacheHandler15_1.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_10.dn b/dat/cache/difffile-large/15/CacheHandler15_10.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_11.dn b/dat/cache/difffile-large/15/CacheHandler15_11.dn new file mode 100644 index 0000000..1a417c7 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_12.dn b/dat/cache/difffile-large/15/CacheHandler15_12.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_13.dn b/dat/cache/difffile-large/15/CacheHandler15_13.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_14.dn b/dat/cache/difffile-large/15/CacheHandler15_14.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_15.dn b/dat/cache/difffile-large/15/CacheHandler15_15.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_16.dn b/dat/cache/difffile-large/15/CacheHandler15_16.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_17.dn b/dat/cache/difffile-large/15/CacheHandler15_17.dn new file mode 100644 index 0000000..0f6afab --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_18.dn b/dat/cache/difffile-large/15/CacheHandler15_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_19.dn b/dat/cache/difffile-large/15/CacheHandler15_19.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_2.dn b/dat/cache/difffile-large/15/CacheHandler15_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_20.dn b/dat/cache/difffile-large/15/CacheHandler15_20.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_21.dn b/dat/cache/difffile-large/15/CacheHandler15_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_22.dn b/dat/cache/difffile-large/15/CacheHandler15_22.dn new file mode 100644 index 0000000..adb6367 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_23.dn b/dat/cache/difffile-large/15/CacheHandler15_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_24.dn b/dat/cache/difffile-large/15/CacheHandler15_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_25.dn b/dat/cache/difffile-large/15/CacheHandler15_25.dn new file mode 100644 index 0000000..9334046 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*13 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_26.dn b/dat/cache/difffile-large/15/CacheHandler15_26.dn new file mode 100644 index 0000000..2e8d0c2 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 19*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_27.dn b/dat/cache/difffile-large/15/CacheHandler15_27.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_28.dn b/dat/cache/difffile-large/15/CacheHandler15_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_29.dn b/dat/cache/difffile-large/15/CacheHandler15_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_3.dn b/dat/cache/difffile-large/15/CacheHandler15_3.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_30.dn b/dat/cache/difffile-large/15/CacheHandler15_30.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_31.dn b/dat/cache/difffile-large/15/CacheHandler15_31.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_32.dn b/dat/cache/difffile-large/15/CacheHandler15_32.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_33.dn b/dat/cache/difffile-large/15/CacheHandler15_33.dn new file mode 100644 index 0000000..fcc56ef --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 11/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_34.dn b/dat/cache/difffile-large/15/CacheHandler15_34.dn new file mode 100644 index 0000000..0f6afab --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_4.dn b/dat/cache/difffile-large/15/CacheHandler15_4.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_5.dn b/dat/cache/difffile-large/15/CacheHandler15_5.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_6.dn b/dat/cache/difffile-large/15/CacheHandler15_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_7.dn b/dat/cache/difffile-large/15/CacheHandler15_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_8.dn b/dat/cache/difffile-large/15/CacheHandler15_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/15/CacheHandler15_9.dn b/dat/cache/difffile-large/15/CacheHandler15_9.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/15/CacheHandler15_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_0.dn b/dat/cache/difffile-large/16/CacheHandler16_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_1.dn b/dat/cache/difffile-large/16/CacheHandler16_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_10.dn b/dat/cache/difffile-large/16/CacheHandler16_10.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_11.dn b/dat/cache/difffile-large/16/CacheHandler16_11.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_12.dn b/dat/cache/difffile-large/16/CacheHandler16_12.dn new file mode 100644 index 0000000..1a417c7 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_13.dn b/dat/cache/difffile-large/16/CacheHandler16_13.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_14.dn b/dat/cache/difffile-large/16/CacheHandler16_14.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_15.dn b/dat/cache/difffile-large/16/CacheHandler16_15.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_16.dn b/dat/cache/difffile-large/16/CacheHandler16_16.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_17.dn b/dat/cache/difffile-large/16/CacheHandler16_17.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_18.dn b/dat/cache/difffile-large/16/CacheHandler16_18.dn new file mode 100644 index 0000000..0f6afab --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_19.dn b/dat/cache/difffile-large/16/CacheHandler16_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_2.dn b/dat/cache/difffile-large/16/CacheHandler16_2.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_20.dn b/dat/cache/difffile-large/16/CacheHandler16_20.dn new file mode 100644 index 0000000..541b5f2 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_21.dn b/dat/cache/difffile-large/16/CacheHandler16_21.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_22.dn b/dat/cache/difffile-large/16/CacheHandler16_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_23.dn b/dat/cache/difffile-large/16/CacheHandler16_23.dn new file mode 100644 index 0000000..adb6367 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_24.dn b/dat/cache/difffile-large/16/CacheHandler16_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_25.dn b/dat/cache/difffile-large/16/CacheHandler16_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_26.dn b/dat/cache/difffile-large/16/CacheHandler16_26.dn new file mode 100644 index 0000000..9334046 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*13 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_27.dn b/dat/cache/difffile-large/16/CacheHandler16_27.dn new file mode 100644 index 0000000..2e8d0c2 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 19*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_28.dn b/dat/cache/difffile-large/16/CacheHandler16_28.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_29.dn b/dat/cache/difffile-large/16/CacheHandler16_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_3.dn b/dat/cache/difffile-large/16/CacheHandler16_3.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_30.dn b/dat/cache/difffile-large/16/CacheHandler16_30.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_31.dn b/dat/cache/difffile-large/16/CacheHandler16_31.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_32.dn b/dat/cache/difffile-large/16/CacheHandler16_32.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_33.dn b/dat/cache/difffile-large/16/CacheHandler16_33.dn new file mode 100644 index 0000000..fcc56ef --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 11/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_34.dn b/dat/cache/difffile-large/16/CacheHandler16_34.dn new file mode 100644 index 0000000..b437d79 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_4.dn b/dat/cache/difffile-large/16/CacheHandler16_4.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_5.dn b/dat/cache/difffile-large/16/CacheHandler16_5.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_6.dn b/dat/cache/difffile-large/16/CacheHandler16_6.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_7.dn b/dat/cache/difffile-large/16/CacheHandler16_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_8.dn b/dat/cache/difffile-large/16/CacheHandler16_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/16/CacheHandler16_9.dn b/dat/cache/difffile-large/16/CacheHandler16_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/16/CacheHandler16_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_0.dn b/dat/cache/difffile-large/17/CacheHandler17_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_1.dn b/dat/cache/difffile-large/17/CacheHandler17_1.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_10.dn b/dat/cache/difffile-large/17/CacheHandler17_10.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_11.dn b/dat/cache/difffile-large/17/CacheHandler17_11.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_12.dn b/dat/cache/difffile-large/17/CacheHandler17_12.dn new file mode 100644 index 0000000..1a417c7 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_13.dn b/dat/cache/difffile-large/17/CacheHandler17_13.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_14.dn b/dat/cache/difffile-large/17/CacheHandler17_14.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_15.dn b/dat/cache/difffile-large/17/CacheHandler17_15.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_16.dn b/dat/cache/difffile-large/17/CacheHandler17_16.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_17.dn b/dat/cache/difffile-large/17/CacheHandler17_17.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_18.dn b/dat/cache/difffile-large/17/CacheHandler17_18.dn new file mode 100644 index 0000000..0f6afab --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_19.dn b/dat/cache/difffile-large/17/CacheHandler17_19.dn new file mode 100644 index 0000000..69c171f --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*3 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_2.dn b/dat/cache/difffile-large/17/CacheHandler17_2.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_20.dn b/dat/cache/difffile-large/17/CacheHandler17_20.dn new file mode 100644 index 0000000..adb6367 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_21.dn b/dat/cache/difffile-large/17/CacheHandler17_21.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_22.dn b/dat/cache/difffile-large/17/CacheHandler17_22.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_23.dn b/dat/cache/difffile-large/17/CacheHandler17_23.dn new file mode 100644 index 0000000..adb6367 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)+nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_24.dn b/dat/cache/difffile-large/17/CacheHandler17_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_25.dn b/dat/cache/difffile-large/17/CacheHandler17_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_26.dn b/dat/cache/difffile-large/17/CacheHandler17_26.dn new file mode 100644 index 0000000..9334046 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*13 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_27.dn b/dat/cache/difffile-large/17/CacheHandler17_27.dn new file mode 100644 index 0000000..2e8d0c2 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 19*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_28.dn b/dat/cache/difffile-large/17/CacheHandler17_28.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_29.dn b/dat/cache/difffile-large/17/CacheHandler17_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_3.dn b/dat/cache/difffile-large/17/CacheHandler17_3.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_30.dn b/dat/cache/difffile-large/17/CacheHandler17_30.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_31.dn b/dat/cache/difffile-large/17/CacheHandler17_31.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_32.dn b/dat/cache/difffile-large/17/CacheHandler17_32.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_33.dn b/dat/cache/difffile-large/17/CacheHandler17_33.dn new file mode 100644 index 0000000..fcc56ef --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 11/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_34.dn b/dat/cache/difffile-large/17/CacheHandler17_34.dn new file mode 100644 index 0000000..b437d79 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_4.dn b/dat/cache/difffile-large/17/CacheHandler17_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_5.dn b/dat/cache/difffile-large/17/CacheHandler17_5.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_6.dn b/dat/cache/difffile-large/17/CacheHandler17_6.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_7.dn b/dat/cache/difffile-large/17/CacheHandler17_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_8.dn b/dat/cache/difffile-large/17/CacheHandler17_8.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/CacheHandler17_9.dn b/dat/cache/difffile-large/17/CacheHandler17_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/17/CacheHandler17_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/17/chromosomes.txt b/dat/cache/difffile-large/17/chromosomes.txt new file mode 100644 index 0000000..5f712b9 --- /dev/null +++ b/dat/cache/difffile-large/17/chromosomes.txt @@ -0,0 +1,35 @@ +index = 0 +index = 0-nthMostFrequentlyUsed(0) +index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) +index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) +index = 0 +index = 0*nthMostRecentlyUsed(0) +index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) +index = 0 +index = 0-nthMostRecentlyUsed(0) +index = 0 +index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) +index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) +index = nthMostRecentlyUsed(0)+nthMostRecentlyUsed(0) +index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) +index = 0/nthMostRecentlyUsed(0) +index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) +index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) +index = 0-nthMostRecentlyUsed(0) +index = nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) +index = 0*3 +index = nthMostFrequentlyUsed(0)+nthMostFrequentlyUsed(0) +index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) +index = 0+nthMostRecentlyUsed(0) +index = nthMostFrequentlyUsed(0)+nthMostFrequentlyUsed(0) +index = 0 +index = 0 +index = nthMostRecentlyUsed(0)*13 +index = 19*nthMostRecentlyUsed(0) +index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) +index = 0 +index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) +index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) +index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) +index = 11/random() +index = nthMostRecentlyUsed(0)-nthMostRecentlyUsed(0) \ No newline at end of file diff --git a/dat/cache/difffile-large/2/CacheHandler2_0.dn b/dat/cache/difffile-large/2/CacheHandler2_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_1.dn b/dat/cache/difffile-large/2/CacheHandler2_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_10.dn b/dat/cache/difffile-large/2/CacheHandler2_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_11.dn b/dat/cache/difffile-large/2/CacheHandler2_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_12.dn b/dat/cache/difffile-large/2/CacheHandler2_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_13.dn b/dat/cache/difffile-large/2/CacheHandler2_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_14.dn b/dat/cache/difffile-large/2/CacheHandler2_14.dn new file mode 100644 index 0000000..b032ee0 --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+15 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_15.dn b/dat/cache/difffile-large/2/CacheHandler2_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_16.dn b/dat/cache/difffile-large/2/CacheHandler2_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_17.dn b/dat/cache/difffile-large/2/CacheHandler2_17.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_18.dn b/dat/cache/difffile-large/2/CacheHandler2_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_19.dn b/dat/cache/difffile-large/2/CacheHandler2_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_2.dn b/dat/cache/difffile-large/2/CacheHandler2_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_20.dn b/dat/cache/difffile-large/2/CacheHandler2_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_21.dn b/dat/cache/difffile-large/2/CacheHandler2_21.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_22.dn b/dat/cache/difffile-large/2/CacheHandler2_22.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_23.dn b/dat/cache/difffile-large/2/CacheHandler2_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_24.dn b/dat/cache/difffile-large/2/CacheHandler2_24.dn new file mode 100644 index 0000000..954e3b6 --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+16 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_25.dn b/dat/cache/difffile-large/2/CacheHandler2_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_26.dn b/dat/cache/difffile-large/2/CacheHandler2_26.dn new file mode 100644 index 0000000..351e233 --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_27.dn b/dat/cache/difffile-large/2/CacheHandler2_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_28.dn b/dat/cache/difffile-large/2/CacheHandler2_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_29.dn b/dat/cache/difffile-large/2/CacheHandler2_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_3.dn b/dat/cache/difffile-large/2/CacheHandler2_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_30.dn b/dat/cache/difffile-large/2/CacheHandler2_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_31.dn b/dat/cache/difffile-large/2/CacheHandler2_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_32.dn b/dat/cache/difffile-large/2/CacheHandler2_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_33.dn b/dat/cache/difffile-large/2/CacheHandler2_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_34.dn b/dat/cache/difffile-large/2/CacheHandler2_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_4.dn b/dat/cache/difffile-large/2/CacheHandler2_4.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_5.dn b/dat/cache/difffile-large/2/CacheHandler2_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_6.dn b/dat/cache/difffile-large/2/CacheHandler2_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_7.dn b/dat/cache/difffile-large/2/CacheHandler2_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_8.dn b/dat/cache/difffile-large/2/CacheHandler2_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/2/CacheHandler2_9.dn b/dat/cache/difffile-large/2/CacheHandler2_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/2/CacheHandler2_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_0.dn b/dat/cache/difffile-large/3/CacheHandler3_0.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_1.dn b/dat/cache/difffile-large/3/CacheHandler3_1.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_10.dn b/dat/cache/difffile-large/3/CacheHandler3_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_11.dn b/dat/cache/difffile-large/3/CacheHandler3_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_12.dn b/dat/cache/difffile-large/3/CacheHandler3_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_13.dn b/dat/cache/difffile-large/3/CacheHandler3_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_14.dn b/dat/cache/difffile-large/3/CacheHandler3_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_15.dn b/dat/cache/difffile-large/3/CacheHandler3_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_16.dn b/dat/cache/difffile-large/3/CacheHandler3_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_17.dn b/dat/cache/difffile-large/3/CacheHandler3_17.dn new file mode 100644 index 0000000..b032ee0 --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+15 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_18.dn b/dat/cache/difffile-large/3/CacheHandler3_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_19.dn b/dat/cache/difffile-large/3/CacheHandler3_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_2.dn b/dat/cache/difffile-large/3/CacheHandler3_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_20.dn b/dat/cache/difffile-large/3/CacheHandler3_20.dn new file mode 100644 index 0000000..9261fe9 --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 18*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_21.dn b/dat/cache/difffile-large/3/CacheHandler3_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_22.dn b/dat/cache/difffile-large/3/CacheHandler3_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_23.dn b/dat/cache/difffile-large/3/CacheHandler3_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_24.dn b/dat/cache/difffile-large/3/CacheHandler3_24.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_25.dn b/dat/cache/difffile-large/3/CacheHandler3_25.dn new file mode 100644 index 0000000..c0b2fdb --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)+3 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_26.dn b/dat/cache/difffile-large/3/CacheHandler3_26.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_27.dn b/dat/cache/difffile-large/3/CacheHandler3_27.dn new file mode 100644 index 0000000..351e233 --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_28.dn b/dat/cache/difffile-large/3/CacheHandler3_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_29.dn b/dat/cache/difffile-large/3/CacheHandler3_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_3.dn b/dat/cache/difffile-large/3/CacheHandler3_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_30.dn b/dat/cache/difffile-large/3/CacheHandler3_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_31.dn b/dat/cache/difffile-large/3/CacheHandler3_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_32.dn b/dat/cache/difffile-large/3/CacheHandler3_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_33.dn b/dat/cache/difffile-large/3/CacheHandler3_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_34.dn b/dat/cache/difffile-large/3/CacheHandler3_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_4.dn b/dat/cache/difffile-large/3/CacheHandler3_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_5.dn b/dat/cache/difffile-large/3/CacheHandler3_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_6.dn b/dat/cache/difffile-large/3/CacheHandler3_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_7.dn b/dat/cache/difffile-large/3/CacheHandler3_7.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_8.dn b/dat/cache/difffile-large/3/CacheHandler3_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/3/CacheHandler3_9.dn b/dat/cache/difffile-large/3/CacheHandler3_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/3/CacheHandler3_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_0.dn b/dat/cache/difffile-large/4/CacheHandler4_0.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_1.dn b/dat/cache/difffile-large/4/CacheHandler4_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_10.dn b/dat/cache/difffile-large/4/CacheHandler4_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_11.dn b/dat/cache/difffile-large/4/CacheHandler4_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_12.dn b/dat/cache/difffile-large/4/CacheHandler4_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_13.dn b/dat/cache/difffile-large/4/CacheHandler4_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_14.dn b/dat/cache/difffile-large/4/CacheHandler4_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_15.dn b/dat/cache/difffile-large/4/CacheHandler4_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_16.dn b/dat/cache/difffile-large/4/CacheHandler4_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_17.dn b/dat/cache/difffile-large/4/CacheHandler4_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_18.dn b/dat/cache/difffile-large/4/CacheHandler4_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_19.dn b/dat/cache/difffile-large/4/CacheHandler4_19.dn new file mode 100644 index 0000000..b032ee0 --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+15 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_2.dn b/dat/cache/difffile-large/4/CacheHandler4_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_20.dn b/dat/cache/difffile-large/4/CacheHandler4_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_21.dn b/dat/cache/difffile-large/4/CacheHandler4_21.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_22.dn b/dat/cache/difffile-large/4/CacheHandler4_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_23.dn b/dat/cache/difffile-large/4/CacheHandler4_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_24.dn b/dat/cache/difffile-large/4/CacheHandler4_24.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_25.dn b/dat/cache/difffile-large/4/CacheHandler4_25.dn new file mode 100644 index 0000000..c0b2fdb --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)+3 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_26.dn b/dat/cache/difffile-large/4/CacheHandler4_26.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_27.dn b/dat/cache/difffile-large/4/CacheHandler4_27.dn new file mode 100644 index 0000000..351e233 --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_28.dn b/dat/cache/difffile-large/4/CacheHandler4_28.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_29.dn b/dat/cache/difffile-large/4/CacheHandler4_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_3.dn b/dat/cache/difffile-large/4/CacheHandler4_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_30.dn b/dat/cache/difffile-large/4/CacheHandler4_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_31.dn b/dat/cache/difffile-large/4/CacheHandler4_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_32.dn b/dat/cache/difffile-large/4/CacheHandler4_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_33.dn b/dat/cache/difffile-large/4/CacheHandler4_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_34.dn b/dat/cache/difffile-large/4/CacheHandler4_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_4.dn b/dat/cache/difffile-large/4/CacheHandler4_4.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_5.dn b/dat/cache/difffile-large/4/CacheHandler4_5.dn new file mode 100644 index 0000000..4e54031 --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 9-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_6.dn b/dat/cache/difffile-large/4/CacheHandler4_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_7.dn b/dat/cache/difffile-large/4/CacheHandler4_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_8.dn b/dat/cache/difffile-large/4/CacheHandler4_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/4/CacheHandler4_9.dn b/dat/cache/difffile-large/4/CacheHandler4_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/4/CacheHandler4_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_0.dn b/dat/cache/difffile-large/5/CacheHandler5_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_1.dn b/dat/cache/difffile-large/5/CacheHandler5_1.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_10.dn b/dat/cache/difffile-large/5/CacheHandler5_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_11.dn b/dat/cache/difffile-large/5/CacheHandler5_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_12.dn b/dat/cache/difffile-large/5/CacheHandler5_12.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_13.dn b/dat/cache/difffile-large/5/CacheHandler5_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_14.dn b/dat/cache/difffile-large/5/CacheHandler5_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_15.dn b/dat/cache/difffile-large/5/CacheHandler5_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_16.dn b/dat/cache/difffile-large/5/CacheHandler5_16.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_17.dn b/dat/cache/difffile-large/5/CacheHandler5_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_18.dn b/dat/cache/difffile-large/5/CacheHandler5_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_19.dn b/dat/cache/difffile-large/5/CacheHandler5_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_2.dn b/dat/cache/difffile-large/5/CacheHandler5_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_20.dn b/dat/cache/difffile-large/5/CacheHandler5_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_21.dn b/dat/cache/difffile-large/5/CacheHandler5_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_22.dn b/dat/cache/difffile-large/5/CacheHandler5_22.dn new file mode 100644 index 0000000..3c39931 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 15/2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_23.dn b/dat/cache/difffile-large/5/CacheHandler5_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_24.dn b/dat/cache/difffile-large/5/CacheHandler5_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_25.dn b/dat/cache/difffile-large/5/CacheHandler5_25.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_26.dn b/dat/cache/difffile-large/5/CacheHandler5_26.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_27.dn b/dat/cache/difffile-large/5/CacheHandler5_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_28.dn b/dat/cache/difffile-large/5/CacheHandler5_28.dn new file mode 100644 index 0000000..351e233 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_29.dn b/dat/cache/difffile-large/5/CacheHandler5_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_3.dn b/dat/cache/difffile-large/5/CacheHandler5_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_30.dn b/dat/cache/difffile-large/5/CacheHandler5_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_31.dn b/dat/cache/difffile-large/5/CacheHandler5_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_32.dn b/dat/cache/difffile-large/5/CacheHandler5_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_33.dn b/dat/cache/difffile-large/5/CacheHandler5_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_34.dn b/dat/cache/difffile-large/5/CacheHandler5_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_4.dn b/dat/cache/difffile-large/5/CacheHandler5_4.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_5.dn b/dat/cache/difffile-large/5/CacheHandler5_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_6.dn b/dat/cache/difffile-large/5/CacheHandler5_6.dn new file mode 100644 index 0000000..e0999a5 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_7.dn b/dat/cache/difffile-large/5/CacheHandler5_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_8.dn b/dat/cache/difffile-large/5/CacheHandler5_8.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/5/CacheHandler5_9.dn b/dat/cache/difffile-large/5/CacheHandler5_9.dn new file mode 100644 index 0000000..4e54031 --- /dev/null +++ b/dat/cache/difffile-large/5/CacheHandler5_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 9-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_0.dn b/dat/cache/difffile-large/6/CacheHandler6_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_1.dn b/dat/cache/difffile-large/6/CacheHandler6_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_10.dn b/dat/cache/difffile-large/6/CacheHandler6_10.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_11.dn b/dat/cache/difffile-large/6/CacheHandler6_11.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_12.dn b/dat/cache/difffile-large/6/CacheHandler6_12.dn new file mode 100644 index 0000000..4e54031 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 9-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_13.dn b/dat/cache/difffile-large/6/CacheHandler6_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_14.dn b/dat/cache/difffile-large/6/CacheHandler6_14.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_15.dn b/dat/cache/difffile-large/6/CacheHandler6_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_16.dn b/dat/cache/difffile-large/6/CacheHandler6_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_17.dn b/dat/cache/difffile-large/6/CacheHandler6_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_18.dn b/dat/cache/difffile-large/6/CacheHandler6_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_19.dn b/dat/cache/difffile-large/6/CacheHandler6_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_2.dn b/dat/cache/difffile-large/6/CacheHandler6_2.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_20.dn b/dat/cache/difffile-large/6/CacheHandler6_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_21.dn b/dat/cache/difffile-large/6/CacheHandler6_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_22.dn b/dat/cache/difffile-large/6/CacheHandler6_22.dn new file mode 100644 index 0000000..3c39931 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 15/2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_23.dn b/dat/cache/difffile-large/6/CacheHandler6_23.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_24.dn b/dat/cache/difffile-large/6/CacheHandler6_24.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_25.dn b/dat/cache/difffile-large/6/CacheHandler6_25.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_26.dn b/dat/cache/difffile-large/6/CacheHandler6_26.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_27.dn b/dat/cache/difffile-large/6/CacheHandler6_27.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_28.dn b/dat/cache/difffile-large/6/CacheHandler6_28.dn new file mode 100644 index 0000000..351e233 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_29.dn b/dat/cache/difffile-large/6/CacheHandler6_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_3.dn b/dat/cache/difffile-large/6/CacheHandler6_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_30.dn b/dat/cache/difffile-large/6/CacheHandler6_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_31.dn b/dat/cache/difffile-large/6/CacheHandler6_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_32.dn b/dat/cache/difffile-large/6/CacheHandler6_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_33.dn b/dat/cache/difffile-large/6/CacheHandler6_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_34.dn b/dat/cache/difffile-large/6/CacheHandler6_34.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_4.dn b/dat/cache/difffile-large/6/CacheHandler6_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_5.dn b/dat/cache/difffile-large/6/CacheHandler6_5.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_6.dn b/dat/cache/difffile-large/6/CacheHandler6_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_7.dn b/dat/cache/difffile-large/6/CacheHandler6_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_8.dn b/dat/cache/difffile-large/6/CacheHandler6_8.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/6/CacheHandler6_9.dn b/dat/cache/difffile-large/6/CacheHandler6_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/6/CacheHandler6_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_0.dn b/dat/cache/difffile-large/7/CacheHandler7_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_1.dn b/dat/cache/difffile-large/7/CacheHandler7_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_10.dn b/dat/cache/difffile-large/7/CacheHandler7_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_11.dn b/dat/cache/difffile-large/7/CacheHandler7_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_12.dn b/dat/cache/difffile-large/7/CacheHandler7_12.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_13.dn b/dat/cache/difffile-large/7/CacheHandler7_13.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_14.dn b/dat/cache/difffile-large/7/CacheHandler7_14.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_15.dn b/dat/cache/difffile-large/7/CacheHandler7_15.dn new file mode 100644 index 0000000..4e54031 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 9-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_16.dn b/dat/cache/difffile-large/7/CacheHandler7_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_17.dn b/dat/cache/difffile-large/7/CacheHandler7_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_18.dn b/dat/cache/difffile-large/7/CacheHandler7_18.dn new file mode 100644 index 0000000..b95d3a3 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_19.dn b/dat/cache/difffile-large/7/CacheHandler7_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_2.dn b/dat/cache/difffile-large/7/CacheHandler7_2.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_20.dn b/dat/cache/difffile-large/7/CacheHandler7_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_21.dn b/dat/cache/difffile-large/7/CacheHandler7_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_22.dn b/dat/cache/difffile-large/7/CacheHandler7_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_23.dn b/dat/cache/difffile-large/7/CacheHandler7_23.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_24.dn b/dat/cache/difffile-large/7/CacheHandler7_24.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_25.dn b/dat/cache/difffile-large/7/CacheHandler7_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_26.dn b/dat/cache/difffile-large/7/CacheHandler7_26.dn new file mode 100644 index 0000000..7168f0c --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*4 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_27.dn b/dat/cache/difffile-large/7/CacheHandler7_27.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_28.dn b/dat/cache/difffile-large/7/CacheHandler7_28.dn new file mode 100644 index 0000000..fd826ac --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_29.dn b/dat/cache/difffile-large/7/CacheHandler7_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_3.dn b/dat/cache/difffile-large/7/CacheHandler7_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_30.dn b/dat/cache/difffile-large/7/CacheHandler7_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_31.dn b/dat/cache/difffile-large/7/CacheHandler7_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_32.dn b/dat/cache/difffile-large/7/CacheHandler7_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_33.dn b/dat/cache/difffile-large/7/CacheHandler7_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_34.dn b/dat/cache/difffile-large/7/CacheHandler7_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_4.dn b/dat/cache/difffile-large/7/CacheHandler7_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_5.dn b/dat/cache/difffile-large/7/CacheHandler7_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_6.dn b/dat/cache/difffile-large/7/CacheHandler7_6.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_7.dn b/dat/cache/difffile-large/7/CacheHandler7_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_8.dn b/dat/cache/difffile-large/7/CacheHandler7_8.dn new file mode 100644 index 0000000..914b79b --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/7/CacheHandler7_9.dn b/dat/cache/difffile-large/7/CacheHandler7_9.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/7/CacheHandler7_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_0.dn b/dat/cache/difffile-large/8/CacheHandler8_0.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_1.dn b/dat/cache/difffile-large/8/CacheHandler8_1.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_10.dn b/dat/cache/difffile-large/8/CacheHandler8_10.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_11.dn b/dat/cache/difffile-large/8/CacheHandler8_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_12.dn b/dat/cache/difffile-large/8/CacheHandler8_12.dn new file mode 100644 index 0000000..914b79b --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_13.dn b/dat/cache/difffile-large/8/CacheHandler8_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_14.dn b/dat/cache/difffile-large/8/CacheHandler8_14.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_15.dn b/dat/cache/difffile-large/8/CacheHandler8_15.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_16.dn b/dat/cache/difffile-large/8/CacheHandler8_16.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_17.dn b/dat/cache/difffile-large/8/CacheHandler8_17.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_18.dn b/dat/cache/difffile-large/8/CacheHandler8_18.dn new file mode 100644 index 0000000..b95d3a3 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_19.dn b/dat/cache/difffile-large/8/CacheHandler8_19.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_2.dn b/dat/cache/difffile-large/8/CacheHandler8_2.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_20.dn b/dat/cache/difffile-large/8/CacheHandler8_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_21.dn b/dat/cache/difffile-large/8/CacheHandler8_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_22.dn b/dat/cache/difffile-large/8/CacheHandler8_22.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_23.dn b/dat/cache/difffile-large/8/CacheHandler8_23.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_24.dn b/dat/cache/difffile-large/8/CacheHandler8_24.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_25.dn b/dat/cache/difffile-large/8/CacheHandler8_25.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_26.dn b/dat/cache/difffile-large/8/CacheHandler8_26.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_27.dn b/dat/cache/difffile-large/8/CacheHandler8_27.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_28.dn b/dat/cache/difffile-large/8/CacheHandler8_28.dn new file mode 100644 index 0000000..fd826ac --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_29.dn b/dat/cache/difffile-large/8/CacheHandler8_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_3.dn b/dat/cache/difffile-large/8/CacheHandler8_3.dn new file mode 100644 index 0000000..4e54031 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 9-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_30.dn b/dat/cache/difffile-large/8/CacheHandler8_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_31.dn b/dat/cache/difffile-large/8/CacheHandler8_31.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_32.dn b/dat/cache/difffile-large/8/CacheHandler8_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_33.dn b/dat/cache/difffile-large/8/CacheHandler8_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_34.dn b/dat/cache/difffile-large/8/CacheHandler8_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_4.dn b/dat/cache/difffile-large/8/CacheHandler8_4.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_5.dn b/dat/cache/difffile-large/8/CacheHandler8_5.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_6.dn b/dat/cache/difffile-large/8/CacheHandler8_6.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_7.dn b/dat/cache/difffile-large/8/CacheHandler8_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_8.dn b/dat/cache/difffile-large/8/CacheHandler8_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/8/CacheHandler8_9.dn b/dat/cache/difffile-large/8/CacheHandler8_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/8/CacheHandler8_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_0.dn b/dat/cache/difffile-large/9/CacheHandler9_0.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_0.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_1.dn b/dat/cache/difffile-large/9/CacheHandler9_1.dn new file mode 100644 index 0000000..219cc47 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_1.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_10.dn b/dat/cache/difffile-large/9/CacheHandler9_10.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_10.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_11.dn b/dat/cache/difffile-large/9/CacheHandler9_11.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_11.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_12.dn b/dat/cache/difffile-large/9/CacheHandler9_12.dn new file mode 100644 index 0000000..f8991fc --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_12.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_13.dn b/dat/cache/difffile-large/9/CacheHandler9_13.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_13.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_14.dn b/dat/cache/difffile-large/9/CacheHandler9_14.dn new file mode 100644 index 0000000..914b79b --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_14.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_15.dn b/dat/cache/difffile-large/9/CacheHandler9_15.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_15.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_16.dn b/dat/cache/difffile-large/9/CacheHandler9_16.dn new file mode 100644 index 0000000..cde4f6e --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_16.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_17.dn b/dat/cache/difffile-large/9/CacheHandler9_17.dn new file mode 100644 index 0000000..627cd48 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_17.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 12-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_18.dn b/dat/cache/difffile-large/9/CacheHandler9_18.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_18.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_19.dn b/dat/cache/difffile-large/9/CacheHandler9_19.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_19.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_2.dn b/dat/cache/difffile-large/9/CacheHandler9_2.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_2.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_20.dn b/dat/cache/difffile-large/9/CacheHandler9_20.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_20.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_21.dn b/dat/cache/difffile-large/9/CacheHandler9_21.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_21.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_22.dn b/dat/cache/difffile-large/9/CacheHandler9_22.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_22.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_23.dn b/dat/cache/difffile-large/9/CacheHandler9_23.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_23.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_24.dn b/dat/cache/difffile-large/9/CacheHandler9_24.dn new file mode 100644 index 0000000..ba9b0dc --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_24.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_25.dn b/dat/cache/difffile-large/9/CacheHandler9_25.dn new file mode 100644 index 0000000..0726947 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_25.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0-2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_26.dn b/dat/cache/difffile-large/9/CacheHandler9_26.dn new file mode 100644 index 0000000..b0adee8 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_26.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_27.dn b/dat/cache/difffile-large/9/CacheHandler9_27.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_27.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_28.dn b/dat/cache/difffile-large/9/CacheHandler9_28.dn new file mode 100644 index 0000000..fd826ac --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_28.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)-nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_29.dn b/dat/cache/difffile-large/9/CacheHandler9_29.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_29.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_3.dn b/dat/cache/difffile-large/9/CacheHandler9_3.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_3.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_30.dn b/dat/cache/difffile-large/9/CacheHandler9_30.dn new file mode 100644 index 0000000..2e02699 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_30.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_31.dn b/dat/cache/difffile-large/9/CacheHandler9_31.dn new file mode 100644 index 0000000..88d4397 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_31.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/random() + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_32.dn b/dat/cache/difffile-large/9/CacheHandler9_32.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_32.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_33.dn b/dat/cache/difffile-large/9/CacheHandler9_33.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_33.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_34.dn b/dat/cache/difffile-large/9/CacheHandler9_34.dn new file mode 100644 index 0000000..ed919b2 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_34.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_4.dn b/dat/cache/difffile-large/9/CacheHandler9_4.dn new file mode 100644 index 0000000..2e42711 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_4.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostRecentlyUsed(0)*nthMostFrequentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_5.dn b/dat/cache/difffile-large/9/CacheHandler9_5.dn new file mode 100644 index 0000000..f70064d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_5.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_6.dn b/dat/cache/difffile-large/9/CacheHandler9_6.dn new file mode 100644 index 0000000..07667c8 --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_6.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0+2 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_7.dn b/dat/cache/difffile-large/9/CacheHandler9_7.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_7.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_8.dn b/dat/cache/difffile-large/9/CacheHandler9_8.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_8.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/cache/difffile-large/9/CacheHandler9_9.dn b/dat/cache/difffile-large/9/CacheHandler9_9.dn new file mode 100644 index 0000000..11e4e2d --- /dev/null +++ b/dat/cache/difffile-large/9/CacheHandler9_9.dn @@ -0,0 +1,267 @@ +/* + * EmerGen(e)tic 0.8 + * Copyright © 2017 Ben Goldsworthy (rumperuu) + * + * A program to research the utility of genetic algorithms, applied to + * 'emergent' sytems. + * + * This file is part of EmerGen(e)tic. + * + * IMPROVEMENT(S): License (probably GNU GPLv3 tbh) goes here. + */ + +/** + ** This program serves as the base for each mutated CacheHandler, + ** providing the functionality that is common to all of them. + **/ + + /** + ** @author Ben Goldsworthy (rumperuu) + ** @version 1.0 + **/ +component provides cache.CacheHandler + requires io.Output out, + data.IntUtil iu, + util.RandomInt ir, + time.Calendar ic, + time.DateUtil du, + io.File { + + static CachedResponse cache[] + static int arraySize + static Mutex cacheLock + + /** + ** Returns a requested item from the cache. + ** + ** @param resource The request item filepath + ** @return The item from the cache + **/ + CachedResponse CacheHandler:getCachedResponse(char filePath[]) { + // Converts the filepath to an array of bytes for the file. + File fd = new File(filePath, File.FILE_ACCESS_READ) + char resource[] = fd.read(fd.getSize()) + fd.close() + + // Returns the item if it's in the cache. + mutex(cacheLock) { + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == resource) { + cache[i].hits++ + cache[i].lastUsed = ic.getTime() + return cache[i] + } + } + } + return null + } + + /** + ** Updates the cache if the requested item is not already present. + ** If the cache is full, the method of determining the item to be + ** replaced is subject to genetic mutation. + ** + ** @param ncr The new item to cache + **/ + void CacheHandler:updateCache(CachedResponse ncr) { + mutex(cacheLock) { + // If the item is already in the cache, do nothing. + for (int i = 0; i < arraySize; i++) { + if (cache[i].resource == ncr.resource) { + cache[i].response = ncr.response + cache[i].resourceAge = ncr.resourceAge + + return + } + } + + // If the item is not, it must be added. + // As `ncr` was created on another component, its details must + // be copied to avoid a read-only exception. + CachedResponse newEntry = new CachedResponse() + newEntry.command = ncr.command + newEntry.resource = ncr.resource + newEntry.resourceAge = ncr.resourceAge + newEntry.mimeType = ncr.mimeType + newEntry.response = new byte[](ncr.response) + newEntry.contentSize = ncr.contentSize + + // Initialises the cache if there isn't currently one. + if (cache == null) { + cache = new CachedResponse[CacheHandler.MAX_SIZE]() + } + + // If the cache is full, determines which item to replace. + if (arraySize == CacheHandler.MAX_SIZE) { + int index + + // BEGIN + index = 0 + // END + + cache[index % arraySize] = newEntry + //out.println("$(debugMSG) replacing: $(iu.intToString(index))") + // Otherwise, appends the item to the end of the cache. + } else { + cache[arraySize] = newEntry + arraySize++ + } + } + } + + /** + ** Clears the cache completely. + **/ + void CacheHandler:clearCache() { + mutex(cacheLock) { + cache = null + } + } + + /************************************************************************** + * What follows are utility functions that a given chromosome of the + * `updateCache()` method may or may not call upon. + **************************************************************************/ + + // This method returns the index of the nth most frequently-used item in + // the cache. + int nthMostFrequentlyUsed(int n) { + int hits[] + for (int i = 0; i < arraySize; i++) hits[i] = 0 + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (cache[i].hits == hits[j]) break + else if (hits[j] == 0) { + hits[j] = cache[i].hits + break + } + } + } + } + + int k = 0 + int nthHit = 0 + for (i = 0; i < j; i++) { + if (hits[i] > nthHit) { + nthHit = hits[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (cache[i].hits == nthHit) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns the index of the nth most recently-used item in + // the cache. + int nthMostRecentlyUsed(int n) { + DateTime useTimes[] + DateTime testTime = ic.getTime() + for (int i = 0; i < arraySize; i++) useTimes[i] = testTime + + int i + int j + mutex(cacheLock) { + for (i = 0; i < arraySize; i++) { + for (j = 0; j < arraySize; j++) { + if (du.equal(cache[i].lastUsed, useTimes[j])) break + else if (du.equal(useTimes[j], testTime)) { + useTimes[j] = cache[i].lastUsed + break + } + } + } + } + + int k = 0 + DateTime nthUseTime = ic.getTime() + for (i = 0; i < j; i++) { + if (du.after(useTimes[i], nthUseTime)) { + nthUseTime = useTimes[i] + k++ + } + if (k == n) break + } + + int itemIndices[] + + mutex(cacheLock) { + j = 0 + for (i = 0; i < arraySize; i++) { + if (du.equal(cache[i].lastUsed, nthUseTime)) itemIndices[j++] = i + } + } + + return resolve(itemIndices, "r") + } + + // This method returns a random index. + int random() { + DateTime dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(CacheHandler.MAX_SIZE) + } + + // This method resolves a multiple return in one of the methods above, + // as per the flag sent along with the list of indices. + // 'n' returns the newest, 'o' the oldest and 'r' a random index. + int resolve(int index[], char flag) { + DateTime dt = null + + if (flag == "n") { + int newestItem = 0 + + int i = index.arrayLength-1 + for (int j = 0; j < index.arrayLength; j++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } else { + if (du.before(dt, cache[index[i]].timeAdded)) { + dt = cache[index[i]].timeAdded + newestItem = index[i] + } + } + i-- + } + + return newestItem + } else if (flag == "o") { + int oldestItem = 0 + + for (int i = 0; i < index.arrayLength; i++) { + if (dt == null) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } else { + if (du.before(cache[index[i]].timeAdded, dt)) { + dt = cache[index[i]].timeAdded + oldestItem = index[i] + } + } + } + return oldestItem + } else if (flag == "r") { + dt = ic.getTime() + int msec = dt.millisecond + ir.setSeed(msec) + return ir.get(index.arrayLength) + } else { + return 0 + } + } +} diff --git a/dat/helloworld/output0.txt b/dat/helloworld/output0.txt new file mode 100644 index 0000000..6798a43 --- /dev/null +++ b/dat/helloworld/output0.txt @@ -0,0 +1,100 @@ + +['Hello world\n', '1_0'] +['Hello world\n', '1_1'] +['Hello world\n', '1_2'] +['Hello world\n', '1_3'] +['Hello world\n', '1_4'] +['Hello world\n', '1_5'] +['Hello world\n', '1_6'] +['Hello world\n', '1_7'] +['Hello world\n', '1_8'] +['Hello world\n', '1_9'] + +['Hello world\n', '2_0'] +['Hello world\n', '2_1'] +['Hello world\n', '2_2'] +['Hello world\n', '2_3'] +['Hello world\n', '2_4'] +['Hello world\n', '2_5'] +['Hello world\n', '2_6'] +['Hello world\n', '2_7'] +['Hello world\n', '2_8'] +['Hello world\n', '2_9'] + +['Hello world\n', '3_0'] +['Hello world\n', '3_1'] +['Hello world\n', '3_2'] +['Hello world\n', '3_3'] +['Hello world\n', '3_4'] +['Hello world\n', '3_5'] +['Hello world\n', '3_6'] +['Hello world\n', '3_7'] +['Hello world\n', '3_8'] +['Hello world\n', '3_9'] + +['Hello world\n', '4_0'] +['Hello world\n', '4_1'] +['Hello world\n', '4_2'] +['Hello world\n', '4_3'] +['Hello world\n', '4_4'] +['Hello world\n', '4_5'] +['Hello world\n', '4_6'] +['Hello world\n', '4_7'] +['Hello world\n', '4_8'] +['Hello world\n', '4_9'] + +['Hello world\n', '5_0'] +['Hello world\n', '5_1'] +['Hello world\n', '5_2'] +['Hello world\n', '5_3'] +['Hello world\n', '5_4'] +['Hello world\n', '5_5'] +['Hello world\n', '5_6'] +['Hello world\n', '5_7'] +['Hello world\n', '5_8'] +['Hello world\n', '5_9'] + +['Hello world\n', '6_0'] +['Hello world\n', '6_1'] +['Hello world\n', '6_2'] +['Hello world\n', '6_3'] +['Hello world\n', '6_4'] +['Hello world\n', '6_5'] +['Hello world\n', '6_6'] +['Hello world\n', '6_7'] +['Hello world\n', '6_8'] +['Hello world\n', '6_9'] + +['Hello world\n', '7_0'] +['Hello world\n', '7_1'] +['Hello world\n', '7_2'] +['Hello world\n', '7_3'] +['Hello world\n', '7_4'] +['Hello world\n', '7_5'] +['Hello world\n', '7_6'] +['Hello world\n', '7_7'] +['Hello world\n', '7_8'] +['Hello world\n', '7_9'] + +['Hello world\n', '8_0'] +['Hello world\n', '8_1'] +['Hello world\n', '8_2'] +['Hello world\n', '8_3'] +['Hello world\n', '8_4'] +['Hello world\n', '8_5'] +['Hello world\n', '8_6'] +['Hello world\n', '8_7'] +['Hello world\n', '8_8'] +['Hello world\n', '8_9'] + +['Hello world\n', '9_0'] +['Hello world\n', '9_1'] +['Hello world\n', '9_2'] +['Hello world\n', '9_3'] +['Hello world\n', '9_4'] +['Hello world\n', '9_5'] +['Hello world\n', '9_6'] +['Hello world\n', '9_7'] +['Hello world\n', '9_8'] +['Hello world\n', '9_9'] + diff --git a/dat/helloworld/output100.txt b/dat/helloworld/output100.txt new file mode 100644 index 0000000..f9c05cb --- /dev/null +++ b/dat/helloworld/output100.txt @@ -0,0 +1,100 @@ + +['ampcjlcutjs', '1_0'] +['xktieosrnyx', '1_1'] +['caxedgtiyup', '1_2'] +['cqyiujnyapp', '1_3'] +['wnkwuyamxxz', '1_4'] +['rfotmkuheyv', '1_5'] +['eveudzvxhzj', '1_6'] +['ftgxinfdomw', '1_7'] +['mdjomfeoggy', '1_8'] +['fibdllxjmox', '1_9'] + +['pwfumdlcauk', '2_0'] +['bfoxwhovtgm', '2_1'] +['gqpztkejijs', '2_2'] +['drxavuclcka', '2_3'] +['wiycvultuli', '2_4'] +['uyxeayumsdc', '2_5'] +['mubbtclbees', '2_6'] +['xezoaznywmq', '2_7'] +['mjlcdtnuekd', '2_8'] +['cdzklmlaayk', '2_9'] + +['dwsvoawkono', '3_0'] +['vokazvphity', '3_1'] +['ogxdqkpodqt', '3_2'] +['rogfabbqmdn', '3_3'] +['ygtasskorjq', '3_4'] +['obpgipyogbm', '3_5'] +['mtpiqcignyk', '3_6'] +['bnzugplaclt', '3_7'] +['dekckrrqqrz', '3_8'] +['jxdbtdrzbka', '3_9'] + +['zeyofehsgel', '4_0'] +['unqpqfgncqq', '4_1'] +['vyirphbzqnv', '4_2'] +['enpjablprua', '4_3'] +['gvnikmusunw', '4_4'] +['bviefpdtdje', '4_5'] +['qogzptxbnsv', '4_6'] +['hjdvmrnewsj', '4_7'] +['kqdetdhygmq', '4_8'] +['xmxqnnwvdxq', '4_9'] + +['oyvocjrkmik', '5_0'] +['ugfnrykhfmr', '5_1'] +['xsqhoxiaduh', '5_2'] +['gkmwhksxzkt', '5_3'] +['rusllvvfgww', '5_4'] +['ozelqmixipj', '5_5'] +['ilmjpwedmrk', '5_6'] +['aptysrjsjkw', '5_7'] +['fmklqkskknf', '5_8'] +['yzekmmmuvul', '5_9'] + +['bitequtywek', '6_0'] +['iqlvnjtermm', '6_1'] +['bvahdtxyrep', '6_2'] +['skxqhsirryo', '6_3'] +['ajoexxutuhd', '6_4'] +['umwormhnxlz', '6_5'] +['htvrrhqgvzl', '6_6'] +['pzitdowgnjg', '6_7'] +['aikbtvejkvr', '6_8'] +['rxttpdhjteo', '6_9'] + +['bghnmmqxksh', '7_0'] +['eqxbhukjhkk', '7_1'] +['pjsplpilhpa', '7_2'] +['fepbzvhjxyd', '7_3'] +['brycqntqkgi', '7_4'] +['ybmnzzqkjbm', '7_5'] +['yovrjairprl', '7_6'] +['lqgfoqrtbhy', '7_7'] +['iwqvaeoyteb', '7_8'] +['cidgqfwqzjm', '7_9'] + +['qcjqmcerknt', '8_0'] +['prziehtdtey', '8_1'] +['oimlyxwgrke', '8_2'] +['nhesujrxtmw', '8_3'] +['vvkbmiupaxk', '8_4'] +['hzvigxvglsh', '8_5'] +['qbvjkftsngc', '8_6'] +['hqkqxkwqnph', '8_7'] +['vafgdyouzia', '8_8'] +['tcdxmxvmzgs', '8_9'] + +['eojplmnbdca', '9_0'] +['bxibnaghyjd', '9_1'] +['wbcjmozsszm', '9_2'] +['bsavrzfzuyp', '9_3'] +['kktmgrnajpc', '9_4'] +['gvrsehcxdkq', '9_5'] +['djgcialnryd', '9_6'] +['dvuwcklknlt', '9_7'] +['hoaxsvpmibw', '9_8'] +['oetzcsckiyu', '9_9'] + diff --git a/dat/helloworld/output50.txt b/dat/helloworld/output50.txt new file mode 100644 index 0000000..253b8c0 --- /dev/null +++ b/dat/helloworld/output50.txt @@ -0,0 +1,100 @@ + +['Hello world\n', '1_0'] +['Hello world\n', '1_1'] +['Hello world\n', '1_2'] +['Hekjo joaky', '1_3'] +['Hello world\n', '1_4'] +['hiblm wokly', '1_5'] +['Hello world\n', '1_6'] +['Hello world\n', '1_7'] +['Hello world\n', '1_8'] +['yeclo wdvld', '1_9'] + +['jmdlo warld', '2_0'] +['Hello wtrld', '2_1'] +['lejlodyowld', '2_2'] +['ijllordokld', '2_3'] +['Htlloikocsd', '2_4'] +['vvkqo wnrzi', '2_5'] +['Hygro wrplf', '2_6'] +['Hello world\n', '2_7'] +['Hellr zxrld', '2_8'] +['tehzy wordd', '2_9'] + +['Hqslo wokad', '3_0'] +['yexerzsorlh', '3_1'] +['lejlodyowld', '3_2'] +['dtvblxworld', '3_3'] +['gelro qorqd', '3_4'] +['vvkqo wnrzi', '3_5'] +['mmlty wxsjd', '3_6'] +['Hello world\n', '3_7'] +['Hellr zxrld', '3_8'] +['tehzy wordd', '3_9'] + +['Hello wonlm', '4_0'] +['ftllo wwalj', '4_1'] +['lejlodyowld', '4_2'] +['Hezun woiue', '4_3'] +['Hqmlo woyir', '4_4'] +['vvkqo wnrzi', '4_5'] +['mmlty wxsjd', '4_6'] +['Hglyo wveld', '4_7'] +['Hellr zxrld', '4_8'] +['meugm wjrlz', '4_9'] + +['Hauln wouyd', '5_0'] +['ftllo wwalj', '5_1'] +['lejlodyowld', '5_2'] +['Hezun woiue', '5_3'] +['Heplo wcrld', '5_4'] +['vvkqo wnrzi', '5_5'] +['qello worfd', '5_6'] +['Hglyo wveld', '5_7'] +['Hlulowwdglj', '5_8'] +['meugm wjrlz', '5_9'] + +['zvumo varqc', '6_0'] +['zvlgo uorlw', '6_1'] +['Hulle woslb', '6_2'] +['Hello wtxid', '6_3'] +['Heplo wcrld', '6_4'] +['vvkqo wnrzi', '6_5'] +['qello worfd', '6_6'] +['Hglyo wveld', '6_7'] +['Hlulowwdglj', '6_8'] +['meugm wjrlz', '6_9'] + +['zvumo varqc', '7_0'] +['Hzlyowwowld', '7_1'] +['Hulle woslb', '7_2'] +['Hnlroemorvc', '7_3'] +['Heltlroorld', '7_4'] +['vvkqo wnrzi', '7_5'] +['peylqxwprnr', '7_6'] +['Hglyo wveld', '7_7'] +['telah zzrod', '7_8'] +['meugm wjrlz', '7_9'] + +['iealouporfy', '8_0'] +['Hzlyowwowld', '8_1'] +['Hulle woslb', '8_2'] +['Hnlroemorvc', '8_3'] +['hezbxgworcd', '8_4'] +['vvkqo wnrzi', '8_5'] +['peylqxwprnr', '8_6'] +['Hglyo wveld', '8_7'] +['thjlh wyhld', '8_8'] +['meugm wjrlz', '8_9'] + +['iealouporfy', '9_0'] +['Hzlyowwowld', '9_1'] +['Hulle woslb', '9_2'] +['Hesho uovms', '9_3'] +['Hehcq forxd', '9_4'] +['vvkqo wnrzi', '9_5'] +['Hrllniwonld', '9_6'] +['Hrjmo wlrkd', '9_7'] +['lehoncworld', '9_8'] +['qejloywztod', '9_9'] + diff --git a/dat/output (normal).txt b/dat/output (normal).txt new file mode 100644 index 0000000..f266bfd --- /dev/null +++ b/dat/output (normal).txt @@ -0,0 +1,648 @@ + +Result for configuration 0x0: 63 ms +Result for configuration 0x1: 21 ms +Result for configuration 0x2: 21 ms +Result for configuration 0x3: 20 ms +Result for configuration 0x4: 21 ms +Result for configuration 0x5: 20 ms +Result for configuration 0x6: 21 ms +Result for configuration 0x7: 21 ms +Result for configuration 0x8: 21 ms +Result for configuration 0x9: 21 ms +Result for configuration 0x10: 20 ms +Result for configuration 0x11: 21 ms +Result for configuration 0x12: 21 ms +Result for configuration 0x13: 20 ms +Result for configuration 0x14: 21 ms +Result for configuration 0x15: 20 ms +Result for configuration 0x16: 21 ms +Result for configuration 0x17: 21 ms +Result for configuration 0x18: 21 ms +Result for configuration 0x19: 21 ms +Result for configuration 0x20: 21 ms +Result for configuration 0x21: 21 ms +Result for configuration 0x22: 21 ms +Result for configuration 0x23: 21 ms +Result for configuration 0x24: 21 ms +Result for configuration 0x25: 21 ms +Result for configuration 0x26: 21 ms +Result for configuration 0x27: 20 ms +Result for configuration 0x28: 21 ms +Result for configuration 0x29: 21 ms +Result for configuration 0x30: 20 ms +Result for configuration 0x31: 21 ms +Result for configuration 0x32: 21 ms +Result for configuration 0x33: 21 ms +Result for configuration 0x34: 21 ms + +Result for configuration 1x0: 21 ms +Result for configuration 1x1: 21 ms +Result for configuration 1x2: 21 ms +Result for configuration 1x3: 21 ms +Result for configuration 1x4: 21 ms +Result for configuration 1x5: 21 ms +Result for configuration 1x6: 20 ms +Result for configuration 1x7: 21 ms +Result for configuration 1x8: 21 ms +Result for configuration 1x9: 21 ms +Result for configuration 1x10: 21 ms +Result for configuration 1x11: 20 ms +Result for configuration 1x12: 21 ms +Result for configuration 1x13: 21 ms +Result for configuration 1x14: 21 ms +Result for configuration 1x15: 21 ms +Result for configuration 1x16: 21 ms +Result for configuration 1x17: 21 ms +Result for configuration 1x18: 21 ms +Result for configuration 1x19: 21 ms +Result for configuration 1x20: 20 ms +Result for configuration 1x21: 21 ms +Result for configuration 1x22: 21 ms +Result for configuration 1x23: 21 ms +Result for configuration 1x24: 21 ms +Result for configuration 1x25: 21 ms +Result for configuration 1x26: 21 ms +Result for configuration 1x27: 21 ms +Result for configuration 1x28: 21 ms +Result for configuration 1x29: 21 ms +Result for configuration 1x30: 21 ms +Result for configuration 1x31: 21 ms +Result for configuration 1x32: 21 ms +Result for configuration 1x33: 21 ms +Result for configuration 1x34: 20 ms + +Result for configuration 2x0: 21 ms +Result for configuration 2x1: 21 ms +Result for configuration 2x2: 21 ms +Result for configuration 2x3: 21 ms +Result for configuration 2x4: 20 ms +Result for configuration 2x5: 21 ms +Result for configuration 2x6: 21 ms +Result for configuration 2x7: 21 ms +Result for configuration 2x8: 21 ms +Result for configuration 2x9: 21 ms +Result for configuration 2x10: 21 ms +Result for configuration 2x11: 21 ms +Result for configuration 2x12: 21 ms +Result for configuration 2x13: 21 ms +Result for configuration 2x14: 21 ms +Result for configuration 2x15: 21 ms +Result for configuration 2x16: 21 ms +Result for configuration 2x17: 21 ms +Result for configuration 2x18: 21 ms +Result for configuration 2x19: 21 ms +Result for configuration 2x20: 22 ms +Result for configuration 2x21: 21 ms +Result for configuration 2x22: 20 ms +Result for configuration 2x23: 20 ms +Result for configuration 2x24: 21 ms +Result for configuration 2x25: 21 ms +Result for configuration 2x26: 21 ms +Result for configuration 2x27: 20 ms +Result for configuration 2x28: 21 ms +Result for configuration 2x29: 21 ms +Result for configuration 2x30: 21 ms +Result for configuration 2x31: 21 ms +Result for configuration 2x32: 21 ms +Result for configuration 2x33: 20 ms +Result for configuration 2x34: 21 ms + +Result for configuration 3x0: 22 ms +Result for configuration 3x1: 21 ms +Result for configuration 3x2: 21 ms +Result for configuration 3x3: 21 ms +Result for configuration 3x4: 21 ms +Result for configuration 3x5: 21 ms +Result for configuration 3x6: 21 ms +Result for configuration 3x7: 20 ms +Result for configuration 3x8: 21 ms +Result for configuration 3x9: 21 ms +Result for configuration 3x10: 21 ms +Result for configuration 3x11: 21 ms +Result for configuration 3x12: 21 ms +Result for configuration 3x13: 20 ms +Result for configuration 3x14: 21 ms +Result for configuration 3x15: 21 ms +Result for configuration 3x16: 21 ms +Result for configuration 3x17: 21 ms +Result for configuration 3x18: 21 ms +Result for configuration 3x19: 20 ms +Result for configuration 3x20: 21 ms +Result for configuration 3x21: 21 ms +Result for configuration 3x22: 20 ms +Result for configuration 3x23: 21 ms +Result for configuration 3x24: 21 ms +Result for configuration 3x25: 21 ms +Result for configuration 3x26: 20 ms +Result for configuration 3x27: 21 ms +Result for configuration 3x28: 20 ms +Result for configuration 3x29: 21 ms +Result for configuration 3x30: 21 ms +Result for configuration 3x31: 21 ms +Result for configuration 3x32: 21 ms +Result for configuration 3x33: 22 ms +Result for configuration 3x34: 21 ms + +Result for configuration 4x0: 21 ms +Result for configuration 4x1: 22 ms +Result for configuration 4x2: 21 ms +Result for configuration 4x3: 22 ms +Result for configuration 4x4: 21 ms +Result for configuration 4x5: 21 ms +Result for configuration 4x6: 21 ms +Result for configuration 4x7: 21 ms +Result for configuration 4x8: 21 ms +Result for configuration 4x9: 21 ms +Result for configuration 4x10: 21 ms +Result for configuration 4x11: 21 ms +Result for configuration 4x12: 21 ms +Result for configuration 4x13: 20 ms +Result for configuration 4x14: 21 ms +Result for configuration 4x15: 21 ms +Result for configuration 4x16: 21 ms +Result for configuration 4x17: 21 ms +Result for configuration 4x18: 21 ms +Result for configuration 4x19: 21 ms +Result for configuration 4x20: 21 ms +Result for configuration 4x21: 20 ms +Result for configuration 4x22: 20 ms +Result for configuration 4x23: 21 ms +Result for configuration 4x24: 21 ms +Result for configuration 4x25: 21 ms +Result for configuration 4x26: 21 ms +Result for configuration 4x27: 21 ms +Result for configuration 4x28: 21 ms +Result for configuration 4x29: 20 ms +Result for configuration 4x30: 21 ms +Result for configuration 4x31: 21 ms +Result for configuration 4x32: 22 ms +Result for configuration 4x33: 21 ms +Result for configuration 4x34: 21 ms + +Result for configuration 5x0: 21 ms +Result for configuration 5x1: 22 ms +Result for configuration 5x2: 22 ms +Result for configuration 5x3: 21 ms +Result for configuration 5x4: 21 ms +Result for configuration 5x5: 21 ms +Result for configuration 5x6: 21 ms +Result for configuration 5x7: 20 ms +Result for configuration 5x8: 21 ms +Result for configuration 5x9: 21 ms +Result for configuration 5x10: 21 ms +Result for configuration 5x11: 20 ms +Result for configuration 5x12: 21 ms +Result for configuration 5x13: 21 ms +Result for configuration 5x14: 21 ms +Result for configuration 5x15: 21 ms +Result for configuration 5x16: 20 ms +Result for configuration 5x17: 21 ms +Result for configuration 5x18: 20 ms +Result for configuration 5x19: 20 ms +Result for configuration 5x20: 20 ms +Result for configuration 5x21: 21 ms +Result for configuration 5x22: 20 ms +Result for configuration 5x23: 21 ms +Result for configuration 5x24: 21 ms +Result for configuration 5x25: 21 ms +Result for configuration 5x26: 21 ms +Result for configuration 5x27: 20 ms +Result for configuration 5x28: 21 ms +Result for configuration 5x29: 20 ms +Result for configuration 5x30: 21 ms +Result for configuration 5x31: 21 ms +Result for configuration 5x32: 21 ms +Result for configuration 5x33: 21 ms +Result for configuration 5x34: 21 ms + +Result for configuration 6x0: 21 ms +Result for configuration 6x1: 21 ms +Result for configuration 6x2: 21 ms +Result for configuration 6x3: 21 ms +Result for configuration 6x4: 21 ms +Result for configuration 6x5: 21 ms +Result for configuration 6x6: 21 ms +Result for configuration 6x7: 21 ms +Result for configuration 6x8: 22 ms +Result for configuration 6x9: 20 ms +Result for configuration 6x10: 21 ms +Result for configuration 6x11: 21 ms +Result for configuration 6x12: 21 ms +Result for configuration 6x13: 22 ms +Result for configuration 6x14: 21 ms +Result for configuration 6x15: 21 ms +Result for configuration 6x16: 21 ms +Result for configuration 6x17: 21 ms +Result for configuration 6x18: 21 ms +Result for configuration 6x19: 21 ms +Result for configuration 6x20: 21 ms +Result for configuration 6x21: 20 ms +Result for configuration 6x22: 21 ms +Result for configuration 6x23: 20 ms +Result for configuration 6x24: 21 ms +Result for configuration 6x25: 21 ms +Result for configuration 6x26: 21 ms +Result for configuration 6x27: 20 ms +Result for configuration 6x28: 21 ms +Result for configuration 6x29: 21 ms +Result for configuration 6x30: 21 ms +Result for configuration 6x31: 21 ms +Result for configuration 6x32: 21 ms +Result for configuration 6x33: 21 ms +Result for configuration 6x34: 21 ms + +Result for configuration 7x0: 22 ms +Result for configuration 7x1: 22 ms +Result for configuration 7x2: 21 ms +Result for configuration 7x3: 22 ms +Result for configuration 7x4: 22 ms +Result for configuration 7x5: 21 ms +Result for configuration 7x6: 21 ms +Result for configuration 7x7: 21 ms +Result for configuration 7x8: 21 ms +Result for configuration 7x9: 20 ms +Result for configuration 7x10: 20 ms +Result for configuration 7x11: 21 ms +Result for configuration 7x12: 21 ms +Result for configuration 7x13: 20 ms +Result for configuration 7x14: 21 ms +Result for configuration 7x15: 20 ms +Result for configuration 7x16: 21 ms +Result for configuration 7x17: 20 ms +Result for configuration 7x18: 21 ms +Result for configuration 7x19: 21 ms +Result for configuration 7x20: 21 ms +Result for configuration 7x21: 21 ms +Result for configuration 7x22: 21 ms +Result for configuration 7x23: 20 ms +Result for configuration 7x24: 21 ms +Result for configuration 7x25: 21 ms +Result for configuration 7x26: 21 ms +Result for configuration 7x27: 20 ms +Result for configuration 7x28: 21 ms +Result for configuration 7x29: 21 ms +Result for configuration 7x30: 21 ms +Result for configuration 7x31: 21 ms +Result for configuration 7x32: 21 ms +Result for configuration 7x33: 21 ms +Result for configuration 7x34: 21 ms + +Result for configuration 8x0: 21 ms +Result for configuration 8x1: 21 ms +Result for configuration 8x2: 21 ms +Result for configuration 8x3: 21 ms +Result for configuration 8x4: 21 ms +Result for configuration 8x5: 21 ms +Result for configuration 8x6: 22 ms +Result for configuration 8x7: 22 ms +Result for configuration 8x8: 21 ms +Result for configuration 8x9: 21 ms +Result for configuration 8x10: 21 ms +Result for configuration 8x11: 21 ms +Result for configuration 8x12: 21 ms +Result for configuration 8x13: 21 ms +Result for configuration 8x14: 21 ms +Result for configuration 8x15: 21 ms +Result for configuration 8x16: 20 ms +Result for configuration 8x17: 21 ms +Result for configuration 8x18: 21 ms +Result for configuration 8x19: 22 ms +Result for configuration 8x20: 21 ms +Result for configuration 8x21: 21 ms +Result for configuration 8x22: 21 ms +Result for configuration 8x23: 20 ms +Result for configuration 8x24: 21 ms +Result for configuration 8x25: 21 ms +Result for configuration 8x26: 21 ms +Result for configuration 8x27: 21 ms +Result for configuration 8x28: 21 ms +Result for configuration 8x29: 21 ms +Result for configuration 8x30: 21 ms +Result for configuration 8x31: 21 ms +Result for configuration 8x32: 21 ms +Result for configuration 8x33: 21 ms +Result for configuration 8x34: 21 ms + +Result for configuration 9x0: 22 ms +Result for configuration 9x1: 21 ms +Result for configuration 9x2: 21 ms +Result for configuration 9x3: 21 ms +Result for configuration 9x4: 21 ms +Result for configuration 9x5: 21 ms +Result for configuration 9x6: 21 ms +Result for configuration 9x7: 21 ms +Result for configuration 9x8: 21 ms +Result for configuration 9x9: 21 ms +Result for configuration 9x10: 21 ms +Result for configuration 9x11: 21 ms +Result for configuration 9x12: 21 ms +Result for configuration 9x13: 21 ms +Result for configuration 9x14: 21 ms +Result for configuration 9x15: 21 ms +Result for configuration 9x16: 21 ms +Result for configuration 9x17: 21 ms +Result for configuration 9x18: 21 ms +Result for configuration 9x19: 20 ms +Result for configuration 9x20: 21 ms +Result for configuration 9x21: 21 ms +Result for configuration 9x22: 21 ms +Result for configuration 9x23: 21 ms +Result for configuration 9x24: 21 ms +Result for configuration 9x25: 21 ms +Result for configuration 9x26: 20 ms +Result for configuration 9x27: 21 ms +Result for configuration 9x28: 21 ms +Result for configuration 9x29: 21 ms +Result for configuration 9x30: 21 ms +Result for configuration 9x31: 21 ms +Result for configuration 9x32: 21 ms +Result for configuration 9x33: 21 ms +Result for configuration 9x34: 21 ms + +Result for configuration 10x0: 22 ms +Result for configuration 10x1: 22 ms +Result for configuration 10x2: 22 ms +Result for configuration 10x3: 21 ms +Result for configuration 10x4: 21 ms +Result for configuration 10x5: 22 ms +Result for configuration 10x6: 22 ms +Result for configuration 10x7: 21 ms +Result for configuration 10x8: 21 ms +Result for configuration 10x9: 21 ms +Result for configuration 10x10: 21 ms +Result for configuration 10x11: 20 ms +Result for configuration 10x12: 22 ms +Result for configuration 10x13: 22 ms +Result for configuration 10x14: 21 ms +Result for configuration 10x15: 21 ms +Result for configuration 10x16: 21 ms +Result for configuration 10x17: 21 ms +Result for configuration 10x18: 21 ms +Result for configuration 10x19: 20 ms +Result for configuration 10x20: 21 ms +Result for configuration 10x21: 21 ms +Result for configuration 10x22: 21 ms +Result for configuration 10x23: 21 ms +Result for configuration 10x24: 20 ms +Result for configuration 10x25: 20 ms +Result for configuration 10x26: 21 ms +Result for configuration 10x27: 21 ms +Result for configuration 10x28: 21 ms +Result for configuration 10x29: 21 ms +Result for configuration 10x30: 21 ms +Result for configuration 10x31: 21 ms +Result for configuration 10x32: 21 ms +Result for configuration 10x33: 21 ms +Result for configuration 10x34: 21 ms + +Result for configuration 11x0: 21 ms +Result for configuration 11x1: 21 ms +Result for configuration 11x2: 22 ms +Result for configuration 11x3: 21 ms +Result for configuration 11x4: 22 ms +Result for configuration 11x5: 22 ms +Result for configuration 11x6: 21 ms +Result for configuration 11x7: 22 ms +Result for configuration 11x8: 21 ms +Result for configuration 11x9: 21 ms +Result for configuration 11x10: 21 ms +Result for configuration 11x11: 21 ms +Result for configuration 11x12: 21 ms +Result for configuration 11x13: 21 ms +Result for configuration 11x14: 22 ms +Result for configuration 11x15: 21 ms +Result for configuration 11x16: 22 ms +Result for configuration 11x17: 21 ms +Result for configuration 11x18: 21 ms +Result for configuration 11x19: 22 ms +Result for configuration 11x20: 21 ms +Result for configuration 11x21: 21 ms +Result for configuration 11x22: 21 ms +Result for configuration 11x23: 21 ms +Result for configuration 11x24: 20 ms +Result for configuration 11x25: 21 ms +Result for configuration 11x26: 21 ms +Result for configuration 11x27: 21 ms +Result for configuration 11x28: 21 ms +Result for configuration 11x29: 21 ms +Result for configuration 11x30: 21 ms +Result for configuration 11x31: 21 ms +Result for configuration 11x32: 21 ms +Result for configuration 11x33: 21 ms +Result for configuration 11x34: 21 ms + +Result for configuration 12x0: 22 ms +Result for configuration 12x1: 21 ms +Result for configuration 12x2: 22 ms +Result for configuration 12x3: 21 ms +Result for configuration 12x4: 21 ms +Result for configuration 12x5: 22 ms +Result for configuration 12x6: 21 ms +Result for configuration 12x7: 21 ms +Result for configuration 12x8: 21 ms +Result for configuration 12x9: 21 ms +Result for configuration 12x10: 21 ms +Result for configuration 12x11: 22 ms +Result for configuration 12x12: 21 ms +Result for configuration 12x13: 22 ms +Result for configuration 12x14: 20 ms +Result for configuration 12x15: 21 ms +Result for configuration 12x16: 21 ms +Result for configuration 12x17: 21 ms +Result for configuration 12x18: 21 ms +Result for configuration 12x19: 21 ms +Result for configuration 12x20: 21 ms +Result for configuration 12x21: 21 ms +Result for configuration 12x22: 21 ms +Result for configuration 12x23: 21 ms +Result for configuration 12x24: 20 ms +Result for configuration 12x25: 21 ms +Result for configuration 12x26: 22 ms +Result for configuration 12x27: 21 ms +Result for configuration 12x28: 21 ms +Result for configuration 12x29: 20 ms +Result for configuration 12x30: 20 ms +Result for configuration 12x31: 21 ms +Result for configuration 12x32: 21 ms +Result for configuration 12x33: 21 ms +Result for configuration 12x34: 21 ms + +Result for configuration 13x0: 22 ms +Result for configuration 13x1: 22 ms +Result for configuration 13x2: 22 ms +Result for configuration 13x3: 21 ms +Result for configuration 13x4: 21 ms +Result for configuration 13x5: 22 ms +Result for configuration 13x6: 22 ms +Result for configuration 13x7: 21 ms +Result for configuration 13x8: 21 ms +Result for configuration 13x9: 22 ms +Result for configuration 13x10: 21 ms +Result for configuration 13x11: 21 ms +Result for configuration 13x12: 21 ms +Result for configuration 13x13: 21 ms +Result for configuration 13x14: 21 ms +Result for configuration 13x15: 21 ms +Result for configuration 13x16: 21 ms +Result for configuration 13x17: 21 ms +Result for configuration 13x18: 21 ms +Result for configuration 13x19: 21 ms +Result for configuration 13x20: 21 ms +Result for configuration 13x21: 20 ms +Result for configuration 13x22: 21 ms +Result for configuration 13x23: 21 ms +Result for configuration 13x24: 21 ms +Result for configuration 13x25: 21 ms +Result for configuration 13x26: 21 ms +Result for configuration 13x27: 21 ms +Result for configuration 13x28: 21 ms +Result for configuration 13x29: 21 ms +Result for configuration 13x30: 21 ms +Result for configuration 13x31: 21 ms +Result for configuration 13x32: 20 ms +Result for configuration 13x33: 21 ms +Result for configuration 13x34: 21 ms + +Result for configuration 14x0: 22 ms +Result for configuration 14x1: 21 ms +Result for configuration 14x2: 22 ms +Result for configuration 14x3: 21 ms +Result for configuration 14x4: 21 ms +Result for configuration 14x5: 21 ms +Result for configuration 14x6: 22 ms +Result for configuration 14x7: 21 ms +Result for configuration 14x8: 21 ms +Result for configuration 14x9: 21 ms +Result for configuration 14x10: 21 ms +Result for configuration 14x11: 21 ms +Result for configuration 14x12: 21 ms +Result for configuration 14x13: 21 ms +Result for configuration 14x14: 21 ms +Result for configuration 14x15: 21 ms +Result for configuration 14x16: 21 ms +Result for configuration 14x17: 21 ms +Result for configuration 14x18: 20 ms +Result for configuration 14x19: 20 ms +Result for configuration 14x20: 21 ms +Result for configuration 14x21: 21 ms +Result for configuration 14x22: 21 ms +Result for configuration 14x23: 21 ms +Result for configuration 14x24: 21 ms +Result for configuration 14x25: 21 ms +Result for configuration 14x26: 21 ms +Result for configuration 14x27: 21 ms +Result for configuration 14x28: 21 ms +Result for configuration 14x29: 21 ms +Result for configuration 14x30: 21 ms +Result for configuration 14x31: 21 ms +Result for configuration 14x32: 21 ms +Result for configuration 14x33: 20 ms +Result for configuration 14x34: 22 ms + +Result for configuration 15x0: 22 ms +Result for configuration 15x1: 22 ms +Result for configuration 15x2: 21 ms +Result for configuration 15x3: 21 ms +Result for configuration 15x4: 21 ms +Result for configuration 15x5: 21 ms +Result for configuration 15x6: 21 ms +Result for configuration 15x7: 22 ms +Result for configuration 15x8: 21 ms +Result for configuration 15x9: 22 ms +Result for configuration 15x10: 22 ms +Result for configuration 15x11: 22 ms +Result for configuration 15x12: 21 ms +Result for configuration 15x13: 21 ms +Result for configuration 15x14: 21 ms +Result for configuration 15x15: 21 ms +Result for configuration 15x16: 21 ms +Result for configuration 15x17: 21 ms +Result for configuration 15x18: 21 ms +Result for configuration 15x19: 21 ms +Result for configuration 15x20: 21 ms +Result for configuration 15x21: 21 ms +Result for configuration 15x22: 21 ms +Result for configuration 15x23: 21 ms +Result for configuration 15x24: 21 ms +Result for configuration 15x25: 21 ms +Result for configuration 15x26: 21 ms +Result for configuration 15x27: 21 ms +Result for configuration 15x28: 20 ms +Result for configuration 15x29: 21 ms +Result for configuration 15x30: 21 ms +Result for configuration 15x31: 21 ms +Result for configuration 15x32: 21 ms +Result for configuration 15x33: 21 ms +Result for configuration 15x34: 21 ms + +Result for configuration 16x0: 21 ms +Result for configuration 16x1: 22 ms +Result for configuration 16x2: 21 ms +Result for configuration 16x3: 22 ms +Result for configuration 16x4: 22 ms +Result for configuration 16x5: 21 ms +Result for configuration 16x6: 21 ms +Result for configuration 16x7: 21 ms +Result for configuration 16x8: 21 ms +Result for configuration 16x9: 22 ms +Result for configuration 16x10: 21 ms +Result for configuration 16x11: 22 ms +Result for configuration 16x12: 22 ms +Result for configuration 16x13: 21 ms +Result for configuration 16x14: 21 ms +Result for configuration 16x15: 22 ms +Result for configuration 16x16: 22 ms +Result for configuration 16x17: 21 ms +Result for configuration 16x18: 21 ms +Result for configuration 16x19: 21 ms +Result for configuration 16x20: 21 ms +Result for configuration 16x21: 21 ms +Result for configuration 16x22: 21 ms +Result for configuration 16x23: 21 ms +Result for configuration 16x24: 21 ms +Result for configuration 16x25: 21 ms +Result for configuration 16x26: 22 ms +Result for configuration 16x27: 21 ms +Result for configuration 16x28: 21 ms +Result for configuration 16x29: 21 ms +Result for configuration 16x30: 21 ms +Result for configuration 16x31: 21 ms +Result for configuration 16x32: 21 ms +Result for configuration 16x33: 21 ms +Result for configuration 16x34: 21 ms + +Result for configuration 17x0: 21 ms +Result for configuration 17x1: 21 ms +Result for configuration 17x2: 21 ms +Result for configuration 17x3: 22 ms +Result for configuration 17x4: 21 ms +Result for configuration 17x5: 22 ms +Result for configuration 17x6: 21 ms +Result for configuration 17x7: 21 ms +Result for configuration 17x8: 21 ms +Result for configuration 17x9: 22 ms +Result for configuration 17x10: 21 ms +Result for configuration 17x11: 21 ms +Result for configuration 17x12: 21 ms +Result for configuration 17x13: 21 ms +Result for configuration 17x14: 21 ms +Result for configuration 17x15: 22 ms +Result for configuration 17x16: 21 ms +Result for configuration 17x17: 22 ms +Result for configuration 17x18: 22 ms +Result for configuration 17x19: 21 ms +Result for configuration 17x20: 21 ms +Result for configuration 17x21: 21 ms +Result for configuration 17x22: 20 ms +Result for configuration 17x23: 21 ms +Result for configuration 17x24: 21 ms +Result for configuration 17x25: 21 ms +Result for configuration 17x26: 21 ms +Result for configuration 17x27: 21 ms +Result for configuration 17x28: 21 ms +Result for configuration 17x29: 21 ms +Result for configuration 17x30: 21 ms +Result for configuration 17x31: 21 ms +Result for configuration 17x32: 21 ms +Result for configuration 17x33: 21 ms +Result for configuration 17x34: 20 ms diff --git a/dat/output (verbose).txt b/dat/output (verbose).txt new file mode 100644 index 0000000..3837ca2 --- /dev/null +++ b/dat/output (verbose).txt @@ -0,0 +1,1027 @@ +Result for configuration 0x0: 21 ms +Result for configuration 0x1: 21 ms +Result for configuration 0x2: 21 ms +Result for configuration 0x3: 21 ms +Result for configuration 0x4: 21 ms +Result for configuration 0x5: 21 ms +Result for configuration 0x6: 21 ms +Result for configuration 0x7: 20 ms +Result for configuration 0x8: 21 ms +Result for configuration 0x9: 21 ms +Result for configuration 0x10: 21 ms +Result for configuration 0x11: 21 ms +Result for configuration 0x12: 21 ms +Result for configuration 0x13: 20 ms +Result for configuration 0x14: 21 ms +Result for configuration 0x15: 21 ms +Result for configuration 0x16: 21 ms +Result for configuration 0x17: 21 ms +Result for configuration 0x18: 20 ms +Result for configuration 0x19: 21 ms +Result for configuration 0x20: 20 ms +Result for configuration 0x21: 20 ms +Result for configuration 0x22: 21 ms +Result for configuration 0x23: 21 ms +Result for configuration 0x24: 21 ms +Result for configuration 0x25: 20 ms +Result for configuration 0x26: 21 ms +Result for configuration 0x27: 20 ms +Result for configuration 0x28: 20 ms +Result for configuration 0x29: 21 ms +Result for configuration 0x30: 21 ms +Result for configuration 0x31: 21 ms +Result for configuration 0x32: 21 ms +Result for configuration 0x33: 21 ms +Result for configuration 0x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 0_3 copied to 1_3 + Result: 0_5 copied to 1_5 + Result: 0_10 copied to 1_10 + Result: 0_13 copied to 1_13 + + +Mutating 0_6->1_6: + Mutating: 0 + Result: 0/13 + Mutating: 0/13 + Result: 0+13 + Mutating: 0+13 + Result: 0+18 +0_6->1_6 mutation finish. + +Mutating 0_7->1_7: + Mutating: 0 + Result: 0*12 + Mutating: 0*12 + Result: 0*12 + Mutating: 0*12 + Result: 0*nthMostRecentlyUsed(0) +0_7->1_7 mutation finish. + +Mutating 0_19->1_19: + Mutating: 0 + Result: 0 +0_19->1_19 mutation finish. + +Mutating 0_21->1_21: + Mutating: 0 + Result: 0*17 + Mutating: 0*17 + Result: 0-17 + Mutating: 0-17 + Result: 0-nthMostFrequentlyUsed(0) +0_21->1_21 mutation finish. + +Mutating 0_25->1_25: + Mutating: 0 + Result: 0 +0_25->1_25 mutation finish. + +Mutating 0_27->1_27: + Mutating: 0 + Result: 0 +0_27->1_27 mutation finish. + +Mutating 0_28->1_28: + Mutating: 0 + Result: 0 +0_28->1_28 mutation finish. + + +Result for configuration 1x0: 21 ms +Result for configuration 1x1: 20 ms +Result for configuration 1x2: 22 ms +Result for configuration 1x3: 22 ms +Result for configuration 1x4: 21 ms +Result for configuration 1x5: 21 ms +Result for configuration 1x6: 21 ms +Result for configuration 1x7: 21 ms +Result for configuration 1x8: 21 ms +Result for configuration 1x9: 21 ms +Result for configuration 1x10: 20 ms +Result for configuration 1x11: 21 ms +Result for configuration 1x12: 21 ms +Result for configuration 1x13: 21 ms +Result for configuration 1x14: 20 ms +Result for configuration 1x15: 21 ms +Result for configuration 1x16: 21 ms +Result for configuration 1x17: 21 ms +Result for configuration 1x18: 21 ms +Result for configuration 1x19: 21 ms +Result for configuration 1x20: 21 ms +Result for configuration 1x21: 21 ms +Result for configuration 1x22: 21 ms +Result for configuration 1x23: 22 ms +Result for configuration 1x24: 21 ms +Result for configuration 1x25: 21 ms +Result for configuration 1x26: 21 ms +Result for configuration 1x27: 21 ms +Result for configuration 1x28: 21 ms +Result for configuration 1x29: 20 ms +Result for configuration 1x30: 20 ms +Result for configuration 1x31: 21 ms +Result for configuration 1x32: 20 ms +Result for configuration 1x33: 21 ms +Result for configuration 1x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 1_6 copied to 2_6 + Result: 1_11 copied to 2_11 + Result: 1_20 copied to 2_20 + Result: 1_34 copied to 2_34 + + +Mutating 1_1->2_1: + Mutating: 0 + Result: 0 +1_1->2_1 mutation finish. + +Mutating 1_14->2_14: + Mutating: 0 + Result: 0*13 + Mutating: 0*13 + Result: 0*13 + Mutating: 0*13 + Result: 0*19 +1_14->2_14 mutation finish. + +Mutating 1_15->2_15: + Mutating: 0 + Result: 0 +1_15->2_15 mutation finish. + +Mutating 1_18->2_18: + Mutating: 0 + Result: 0*16 + Mutating: 0*16 + Result: 0/16 + Mutating: 0/16 + Result: 0/3 +1_18->2_18 mutation finish. + +Mutating 1_21->2_21: + Mutating: 0-nthMostFrequentlyUsed(0) + Result: 5-nthMostFrequentlyUsed(0) + Mutating: 5-nthMostFrequentlyUsed(0) + Result: 5-nthMostFrequentlyUsed(0) + Mutating: 5-nthMostFrequentlyUsed(0) + Result: 5-nthMostFrequentlyUsed(0) + Mutating: 5-nthMostFrequentlyUsed(0) + Result: 5-nthMostFrequentlyUsed(0) +1_21->2_21 mutation finish. + +Mutating 1_23->2_23: + Mutating: 0 + Result: 0+11 + Mutating: 0+11 + Result: 0-11 + Mutating: 0-11 + Result: 0-nthMostFrequentlyUsed(0) +1_23->2_23 mutation finish. + +Mutating 1_25->2_25: + Mutating: 0 + Result: 0/3 + Mutating: 0/3 + Result: 0/3 + Mutating: 0/3 + Result: 0/nthMostRecentlyUsed(0) +1_25->2_25 mutation finish. + +Mutating 1_27->2_27: + Mutating: 0 + Result: 0*9 + Mutating: 0*9 + Result: 0/9 + Mutating: 0/9 + Result: 0/3 +1_27->2_27 mutation finish. + + +Result for configuration 2x0: 21 ms +Result for configuration 2x1: 21 ms +Result for configuration 2x2: 20 ms +Result for configuration 2x3: 21 ms +Result for configuration 2x4: 20 ms +Result for configuration 2x5: 21 ms +Result for configuration 2x6: 20 ms +Result for configuration 2x7: 22 ms +Result for configuration 2x8: 22 ms +Result for configuration 2x9: 21 ms +Result for configuration 2x10: 21 ms +Result for configuration 2x11: 22 ms +Result for configuration 2x12: 21 ms +Result for configuration 2x13: 21 ms +Result for configuration 2x14: 21 ms +Result for configuration 2x15: 21 ms +Result for configuration 2x16: 21 ms +Result for configuration 2x17: 21 ms +Result for configuration 2x18: 20 ms +Result for configuration 2x19: 21 ms +Result for configuration 2x20: 21 ms +Result for configuration 2x21: 20 ms +Result for configuration 2x22: 21 ms +Result for configuration 2x23: 21 ms +Result for configuration 2x24: 21 ms +Result for configuration 2x25: 21 ms +Result for configuration 2x26: 21 ms +Result for configuration 2x27: 21 ms +Result for configuration 2x28: 21 ms +Result for configuration 2x29: 21 ms +Result for configuration 2x30: 21 ms +Result for configuration 2x31: 20 ms +Result for configuration 2x32: 21 ms +Result for configuration 2x33: 21 ms +Result for configuration 2x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 2_4 copied to 3_4 + Result: 2_22 copied to 3_22 + Result: 2_23 copied to 3_23 + Result: 2_27 copied to 3_27 + + +Mutating 2_6->3_6: + Mutating: 0 + Result: 0+1 + Mutating: 0+1 + Result: 0+1 + Mutating: 0+1 + Result: 0+random() +2_6->3_6 mutation finish. + +Mutating 2_12->3_12: + Mutating: 0*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) +2_12->3_12 mutation finish. + +Mutating 2_16->3_16: + Mutating: 0*19 + Result: nthMostRecentlyUsed(0)*19 + Mutating: nthMostRecentlyUsed(0)*19 + Result: nthMostRecentlyUsed(0)-19 + Mutating: nthMostRecentlyUsed(0)-19 + Result: nthMostRecentlyUsed(0)-9 +2_16->3_16 mutation finish. + +Mutating 2_19->3_19: + Mutating: 0 + Result: 0 +2_19->3_19 mutation finish. + +Mutating 2_20->3_20: + Mutating: 0/3 + Result: nthMostFrequentlyUsed(0)/3 + Mutating: nthMostFrequentlyUsed(0)/3 + Result: nthMostFrequentlyUsed(0)+3 + Mutating: nthMostFrequentlyUsed(0)+3 + Result: nthMostFrequentlyUsed(0)+2 +2_20->3_20 mutation finish. + +Mutating 2_21->3_21: + Mutating: 0 + Result: 0+19 + Mutating: 0+19 + Result: 0*19 + Mutating: 0*19 + Result: 0*nthMostRecentlyUsed(0) +2_21->3_21 mutation finish. + +Mutating 2_31->3_31: + Mutating: 0 + Result: 0/2 + Mutating: 0/2 + Result: 0+2 + Mutating: 0+2 + Result: 0+nthMostRecentlyUsed(0) +2_31->3_31 mutation finish. + +Mutating 2_32->3_32: + Mutating: 0 + Result: 0 +2_32->3_32 mutation finish. + +Mutating 2_33->3_33: + Mutating: 0 + Result: 0 +2_33->3_33 mutation finish. + + +Result for configuration 3x0: 22 ms +Result for configuration 3x1: 21 ms +Result for configuration 3x2: 21 ms +Result for configuration 3x3: 20 ms +Result for configuration 3x4: 22 ms +Result for configuration 3x5: 21 ms +Result for configuration 3x6: 21 ms +Result for configuration 3x7: 21 ms +Result for configuration 3x8: 20 ms +Result for configuration 3x9: 21 ms +Result for configuration 3x10: 21 ms +Result for configuration 3x11: 20 ms +Result for configuration 3x12: 21 ms +Result for configuration 3x13: 20 ms +Result for configuration 3x14: 20 ms +Result for configuration 3x15: 21 ms +Result for configuration 3x16: 20 ms +Result for configuration 3x17: 21 ms +Result for configuration 3x18: 20 ms +Result for configuration 3x19: 20 ms +Result for configuration 3x20: 21 ms +Result for configuration 3x21: 20 ms +Result for configuration 3x22: 21 ms +Result for configuration 3x23: 21 ms +Result for configuration 3x24: 21 ms +Result for configuration 3x25: 21 ms +Result for configuration 3x26: 21 ms +Result for configuration 3x27: 21 ms +Result for configuration 3x28: 21 ms +Result for configuration 3x29: 21 ms +Result for configuration 3x30: 21 ms +Result for configuration 3x31: 20 ms +Result for configuration 3x32: 20 ms +Result for configuration 3x33: 21 ms +Result for configuration 3x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 3_7 copied to 4_7 + Result: 3_13 copied to 4_13 + Result: 3_19 copied to 4_19 + Result: 3_22 copied to 4_22 + + +Mutating 3_15->4_15: + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) +3_15->4_15 mutation finish. + +Mutating 3_18->4_18: + Mutating: 0 + Result: 0+12 + Mutating: 0+12 + Result: 0+12 + Mutating: 0+12 + Result: 0+nthMostRecentlyUsed(0) +3_18->4_18 mutation finish. + +Mutating 3_26->4_26: + Mutating: 0 + Result: 0/8 + Mutating: 0/8 + Result: 0/8 + Mutating: 0/8 + Result: 0/nthMostRecentlyUsed(0) +3_26->4_26 mutation finish. + +Mutating 3_32->4_32: + Mutating: 0 + Result: 0-3 + Mutating: 0-3 + Result: 0-3 + Mutating: 0-3 + Result: 0-nthMostRecentlyUsed(0) +3_32->4_32 mutation finish. + + +Result for configuration 4x0: 21 ms +Result for configuration 4x1: 21 ms +Result for configuration 4x2: 21 ms +Result for configuration 4x3: 21 ms +Result for configuration 4x4: 21 ms +Result for configuration 4x5: 20 ms +Result for configuration 4x6: 21 ms +Result for configuration 4x7: 21 ms +Result for configuration 4x8: 21 ms +Result for configuration 4x9: 21 ms +Result for configuration 4x10: 21 ms +Result for configuration 4x11: 21 ms +Result for configuration 4x12: 21 ms +Result for configuration 4x13: 20 ms +Result for configuration 4x14: 21 ms +Result for configuration 4x15: 20 ms +Result for configuration 4x16: 20 ms +Result for configuration 4x17: 21 ms +Result for configuration 4x18: 21 ms +Result for configuration 4x19: 20 ms +Result for configuration 4x20: 21 ms +Result for configuration 4x21: 21 ms +Result for configuration 4x22: 20 ms +Result for configuration 4x23: 21 ms +Result for configuration 4x24: 21 ms +Result for configuration 4x25: 20 ms +Result for configuration 4x26: 21 ms +Result for configuration 4x27: 21 ms +Result for configuration 4x28: 20 ms +Result for configuration 4x29: 21 ms +Result for configuration 4x30: 21 ms +Result for configuration 4x31: 20 ms +Result for configuration 4x32: 21 ms +Result for configuration 4x33: 21 ms +Result for configuration 4x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 4_13 copied to 5_13 + Result: 4_21 copied to 5_21 + Result: 4_22 copied to 5_22 + Result: 4_29 copied to 5_29 + + +Mutating 4_2->5_2: + Mutating: nthMostRecentlyUsed(0)-9 + Result: nthMostRecentlyUsed(0)-9 + Mutating: nthMostRecentlyUsed(0)-9 + Result: nthMostRecentlyUsed(0)-9 + Mutating: nthMostRecentlyUsed(0)-9 + Result: nthMostRecentlyUsed(0)-9 + Mutating: nthMostRecentlyUsed(0)-9 + Result: nthMostRecentlyUsed(0)-nthMostRecentlyUsed(0) +4_2->5_2 mutation finish. + +Mutating 4_8->5_8: + Mutating: 0 + Result: 0/11 + Mutating: 0/11 + Result: 0/11 + Mutating: 0/11 + Result: 0/nthMostRecentlyUsed(0) +4_8->5_8 mutation finish. + +Mutating 4_9->5_9: + Mutating: 0 + Result: 0 +4_9->5_9 mutation finish. + +Mutating 4_12->5_12: + Mutating: 0+random() + Result: nthMostFrequentlyUsed(0)+random() + Mutating: nthMostFrequentlyUsed(0)+random() + Result: nthMostFrequentlyUsed(0)/random() + Mutating: nthMostFrequentlyUsed(0)/random() + Result: nthMostFrequentlyUsed(0)/random() +4_12->5_12 mutation finish. + +Mutating 4_20->5_20: + Mutating: 0+nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)+nthMostRecentlyUsed(0) + Mutating: nthMostFrequentlyUsed(0)+nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)*nthMostRecentlyUsed(0) +4_20->5_20 mutation finish. + +Mutating 4_34->5_34: + Mutating: 0 + Result: 0/5 + Mutating: 0/5 + Result: 0+5 + Mutating: 0+5 + Result: 0+nthMostRecentlyUsed(0) +4_34->5_34 mutation finish. + + +Result for configuration 5x0: 21 ms +Result for configuration 5x1: 22 ms +Result for configuration 5x2: 21 ms +Result for configuration 5x3: 22 ms +Result for configuration 5x4: 21 ms +Result for configuration 5x5: 20 ms +Result for configuration 5x6: 20 ms +Result for configuration 5x7: 21 ms +Result for configuration 5x8: 20 ms +Result for configuration 5x9: 20 ms +Result for configuration 5x10: 21 ms +Result for configuration 5x11: 22 ms +Result for configuration 5x12: 21 ms +Result for configuration 5x13: 21 ms +Result for configuration 5x14: 21 ms +Result for configuration 5x15: 20 ms +Result for configuration 5x16: 21 ms +Result for configuration 5x17: 20 ms +Result for configuration 5x18: 21 ms +Result for configuration 5x19: 21 ms +Result for configuration 5x20: 21 ms +Result for configuration 5x21: 21 ms +Result for configuration 5x22: 21 ms +Result for configuration 5x23: 21 ms +Result for configuration 5x24: 21 ms +Result for configuration 5x25: 21 ms +Result for configuration 5x26: 20 ms +Result for configuration 5x27: 20 ms +Result for configuration 5x28: 21 ms +Result for configuration 5x29: 21 ms +Result for configuration 5x30: 20 ms +Result for configuration 5x31: 20 ms +Result for configuration 5x32: 21 ms +Result for configuration 5x33: 21 ms +Result for configuration 5x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 5_7 copied to 6_7 + Result: 5_11 copied to 6_11 + Result: 5_16 copied to 6_16 + Result: 5_18 copied to 6_18 + + +Mutating 5_0->6_0: + Mutating: 0 + Result: 0/9 + Mutating: 0/9 + Result: 0/9 + Mutating: 0/9 + Result: 0/nthMostRecentlyUsed(0) +5_0->6_0 mutation finish. + +Mutating 5_8->6_8: + Mutating: 0 + Result: 0 +5_8->6_8 mutation finish. + +Mutating 5_30->6_30: + Mutating: 0 + Result: 0-16 + Mutating: 0-16 + Result: 0+16 + Mutating: 0+16 + Result: 0+nthMostFrequentlyUsed(0) +5_30->6_30 mutation finish. + + +Result for configuration 6x0: 21 ms +Result for configuration 6x1: 21 ms +Result for configuration 6x2: 21 ms +Result for configuration 6x3: 21 ms +Result for configuration 6x4: 21 ms +Result for configuration 6x5: 21 ms +Result for configuration 6x6: 21 ms +Result for configuration 6x7: 20 ms +Result for configuration 6x8: 21 ms +Result for configuration 6x9: 20 ms +Result for configuration 6x10: 21 ms +Result for configuration 6x11: 21 ms +Result for configuration 6x12: 21 ms +Result for configuration 6x13: 20 ms +Result for configuration 6x14: 21 ms +Result for configuration 6x15: 21 ms +Result for configuration 6x16: 21 ms +Result for configuration 6x17: 20 ms +Result for configuration 6x18: 21 ms +Result for configuration 6x19: 21 ms +Result for configuration 6x20: 21 ms +Result for configuration 6x21: 21 ms +Result for configuration 6x22: 21 ms +Result for configuration 6x23: 21 ms +Result for configuration 6x24: 21 ms +Result for configuration 6x25: 21 ms +Result for configuration 6x26: 21 ms +Result for configuration 6x27: 20 ms +Result for configuration 6x28: 21 ms +Result for configuration 6x29: 20 ms +Result for configuration 6x30: 20 ms +Result for configuration 6x31: 21 ms +Result for configuration 6x32: 20 ms +Result for configuration 6x33: 20 ms +Result for configuration 6x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 6_9 copied to 7_9 + Result: 6_21 copied to 7_21 + Result: 6_23 copied to 7_23 + Result: 6_27 copied to 7_27 + + +Mutating 6_20->7_20: + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)*nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) +6_20->7_20 mutation finish. + +Mutating 6_22->7_22: + Mutating: 0 + Result: 0/8 + Mutating: 0/8 + Result: 0/8 + Mutating: 0/8 + Result: 0/nthMostFrequentlyUsed(0) +6_22->7_22 mutation finish. + +Mutating 6_26->7_26: + Mutating: 0-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) +6_26->7_26 mutation finish. + + +Result for configuration 7x0: 21 ms +Result for configuration 7x1: 21 ms +Result for configuration 7x2: 21 ms +Result for configuration 7x3: 21 ms +Result for configuration 7x4: 21 ms +Result for configuration 7x5: 22 ms +Result for configuration 7x6: 21 ms +Result for configuration 7x7: 21 ms +Result for configuration 7x8: 21 ms +Result for configuration 7x9: 21 ms +Result for configuration 7x10: 21 ms +Result for configuration 7x11: 20 ms +Result for configuration 7x12: 21 ms +Result for configuration 7x13: 21 ms +Result for configuration 7x14: 21 ms +Result for configuration 7x15: 21 ms +Result for configuration 7x16: 21 ms +Result for configuration 7x17: 21 ms +Result for configuration 7x18: 21 ms +Result for configuration 7x19: 20 ms +Result for configuration 7x20: 21 ms +Result for configuration 7x21: 21 ms +Result for configuration 7x22: 20 ms +Result for configuration 7x23: 21 ms +Result for configuration 7x24: 21 ms +Result for configuration 7x25: 21 ms +Result for configuration 7x26: 21 ms +Result for configuration 7x27: 20 ms +Result for configuration 7x28: 21 ms +Result for configuration 7x29: 20 ms +Result for configuration 7x30: 21 ms +Result for configuration 7x31: 21 ms +Result for configuration 7x32: 21 ms +Result for configuration 7x33: 21 ms +Result for configuration 7x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 7_9 copied to 8_9 + Result: 7_10 copied to 8_10 + Result: 7_13 copied to 8_13 + Result: 7_15 copied to 8_15 + + +Mutating 7_1->8_1: + Mutating: 0 + Result: 0 +7_1->8_1 mutation finish. + +Mutating 7_6->8_6: + Mutating: nthMostFrequentlyUsed(0)/random() + Result: nthMostFrequentlyUsed(0)/random() + Mutating: nthMostFrequentlyUsed(0)/random() + Result: nthMostFrequentlyUsed(0)/random() + Mutating: nthMostFrequentlyUsed(0)/random() + Result: nthMostFrequentlyUsed(0)/random() + Mutating: nthMostFrequentlyUsed(0)/random() + Result: nthMostFrequentlyUsed(0)/random() +7_6->8_6 mutation finish. + +Mutating 7_12->8_12: + Mutating: 0 + Result: 0 +7_12->8_12 mutation finish. + +Mutating 7_27->8_27: + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) + Result: nthMostRecentlyUsed(0)-nthMostFrequentlyUsed(0) +7_27->8_27 mutation finish. + +Mutating 7_28->8_28: + Mutating: 0/nthMostRecentlyUsed(0) + Result: 9/nthMostRecentlyUsed(0) + Mutating: 9/nthMostRecentlyUsed(0) + Result: 9/nthMostRecentlyUsed(0) + Mutating: 9/nthMostRecentlyUsed(0) + Result: 9/nthMostRecentlyUsed(0) + Mutating: 9/nthMostRecentlyUsed(0) + Result: 9/nthMostRecentlyUsed(0) +7_28->8_28 mutation finish. + + +Result for configuration 8x0: 21 ms +Result for configuration 8x1: 21 ms +Result for configuration 8x2: 21 ms +Result for configuration 8x3: 21 ms +Result for configuration 8x4: 21 ms +Result for configuration 8x5: 21 ms +Result for configuration 8x6: 21 ms +Result for configuration 8x7: 22 ms +Result for configuration 8x8: 21 ms +Result for configuration 8x9: 20 ms +Result for configuration 8x10: 21 ms +Result for configuration 8x11: 21 ms +Result for configuration 8x12: 21 ms +Result for configuration 8x13: 21 ms +Result for configuration 8x14: 22 ms +Result for configuration 8x15: 21 ms +Result for configuration 8x16: 21 ms +Result for configuration 8x17: 20 ms +Result for configuration 8x18: 21 ms +Result for configuration 8x19: 21 ms +Result for configuration 8x20: 21 ms +Result for configuration 8x21: 21 ms +Result for configuration 8x22: 21 ms +Result for configuration 8x23: 20 ms +Result for configuration 8x24: 21 ms +Result for configuration 8x25: 21 ms +Result for configuration 8x26: 21 ms +Result for configuration 8x27: 21 ms +Result for configuration 8x28: 21 ms +Result for configuration 8x29: 20 ms +Result for configuration 8x30: 21 ms +Result for configuration 8x31: 21 ms +Result for configuration 8x32: 21 ms +Result for configuration 8x33: 21 ms +Result for configuration 8x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 8_16 copied to 9_16 + Result: 8_23 copied to 9_23 + Result: 8_9 copied to 9_9 + Result: 8_17 copied to 9_17 + + +Mutating 8_14->9_14: + Mutating: 0 + Result: 0-5 + Mutating: 0-5 + Result: 0-5 + Mutating: 0-5 + Result: 0-8 +8_14->9_14 mutation finish. + +Mutating 8_15->9_15: + Mutating: 0 + Result: 0/9 + Mutating: 0/9 + Result: 0/9 + Mutating: 0/9 + Result: 0/6 +8_15->9_15 mutation finish. + +Mutating 8_31->9_31: + Mutating: 0+nthMostRecentlyUsed(0) + Result: 3+nthMostRecentlyUsed(0) + Mutating: 3+nthMostRecentlyUsed(0) + Result: 3/nthMostRecentlyUsed(0) + Mutating: 3/nthMostRecentlyUsed(0) + Result: 3/nthMostRecentlyUsed(0) + Mutating: 3/nthMostRecentlyUsed(0) + Result: 3/nthMostRecentlyUsed(0) +8_31->9_31 mutation finish. + +Mutating 8_34->9_34: + Mutating: 0+nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)+nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)+nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) +8_34->9_34 mutation finish. + + +Result for configuration 9x0: 21 ms +Result for configuration 9x1: 21 ms +Result for configuration 9x2: 21 ms +Result for configuration 9x3: 21 ms +Result for configuration 9x4: 21 ms +Result for configuration 9x5: 21 ms +Result for configuration 9x6: 22 ms +Result for configuration 9x7: 22 ms +Result for configuration 9x8: 21 ms +Result for configuration 9x9: 21 ms +Result for configuration 9x10: 21 ms +Result for configuration 9x11: 21 ms +Result for configuration 9x12: 21 ms +Result for configuration 9x13: 20 ms +Result for configuration 9x14: 20 ms +Result for configuration 9x15: 21 ms +Result for configuration 9x16: 20 ms +Result for configuration 9x17: 21 ms +Result for configuration 9x18: 20 ms +Result for configuration 9x19: 21 ms +Result for configuration 9x20: 21 ms +Result for configuration 9x21: 20 ms +Result for configuration 9x22: 21 ms +Result for configuration 9x23: 21 ms +Result for configuration 9x24: 21 ms +Result for configuration 9x25: 21 ms +Result for configuration 9x26: 20 ms +Result for configuration 9x27: 21 ms +Result for configuration 9x28: 21 ms +Result for configuration 9x29: 21 ms +Result for configuration 9x30: 20 ms +Result for configuration 9x31: 20 ms +Result for configuration 9x32: 21 ms +Result for configuration 9x33: 21 ms +Result for configuration 9x34: 20 ms + +Applying rank selection to top 10% from prev. generation... + Result: 9_19 copied to 10_19 + Result: 9_26 copied to 10_26 + Result: 9_13 copied to 10_13 + Result: 9_14 copied to 10_14 + + +Mutating 9_4->10_4: + Mutating: 0 + Result: 0/14 + Mutating: 0/14 + Result: 0/14 + Mutating: 0/14 + Result: 0/nthMostRecentlyUsed(0) +9_4->10_4 mutation finish. + +Mutating 9_12->10_12: + Mutating: 0 + Result: 0 +9_12->10_12 mutation finish. + +Mutating 9_31->10_31: + Mutating: 3/nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostFrequentlyUsed(0)/nthMostRecentlyUsed(0) +9_31->10_31 mutation finish. + +Mutating 9_34->10_34: + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) +9_34->10_34 mutation finish. + + +Result for configuration 10x0: 21 ms +Result for configuration 10x1: 21 ms +Result for configuration 10x2: 21 ms +Result for configuration 10x3: 21 ms +Result for configuration 10x4: 21 ms +Result for configuration 10x5: 21 ms +Result for configuration 10x6: 21 ms +Result for configuration 10x7: 21 ms +Result for configuration 10x8: 21 ms +Result for configuration 10x9: 21 ms +Result for configuration 10x10: 20 ms +Result for configuration 10x11: 21 ms +Result for configuration 10x12: 21 ms +Result for configuration 10x13: 21 ms +Result for configuration 10x14: 21 ms +Result for configuration 10x15: 20 ms +Result for configuration 10x16: 21 ms +Result for configuration 10x17: 21 ms +Result for configuration 10x18: 21 ms +Result for configuration 10x19: 21 ms +Result for configuration 10x20: 20 ms +Result for configuration 10x21: 21 ms +Result for configuration 10x22: 21 ms +Result for configuration 10x23: 21 ms +Result for configuration 10x24: 21 ms +Result for configuration 10x25: 20 ms +Result for configuration 10x26: 20 ms +Result for configuration 10x27: 21 ms +Result for configuration 10x28: 21 ms +Result for configuration 10x29: 21 ms +Result for configuration 10x30: 21 ms +Result for configuration 10x31: 21 ms +Result for configuration 10x32: 21 ms +Result for configuration 10x33: 20 ms +Result for configuration 10x34: 21 ms + +Applying rank selection to top 10% from prev. generation... + Result: 10_11 copied to 11_11 + Result: 10_19 copied to 11_19 + Result: 10_24 copied to 11_24 + Result: 10_25 copied to 11_25 + + +Mutating 10_8->11_8: + Mutating: 0/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) +10_8->11_8 mutation finish. + +Mutating 10_20->11_20: + Mutating: 0/6 + Result: nthMostRecentlyUsed(0)/6 + Mutating: nthMostRecentlyUsed(0)/6 + Result: nthMostRecentlyUsed(0)+6 + Mutating: nthMostRecentlyUsed(0)+6 + Result: nthMostRecentlyUsed(0)+nthMostFrequentlyUsed(0) +10_20->11_20 mutation finish. + +Mutating 10_26->11_26: + Mutating: nthMostFrequentlyUsed(0)+2 + Result: nthMostFrequentlyUsed(0)+2 + Mutating: nthMostFrequentlyUsed(0)+2 + Result: nthMostFrequentlyUsed(0)+2 + Mutating: nthMostFrequentlyUsed(0)+2 + Result: nthMostFrequentlyUsed(0)+2 + Mutating: nthMostFrequentlyUsed(0)+2 + Result: nthMostFrequentlyUsed(0)+17 +10_26->11_26 mutation finish. + +Mutating 10_28->11_28: + Mutating: 9/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Mutating: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) + Result: nthMostRecentlyUsed(0)/nthMostRecentlyUsed(0) +10_28->11_28 mutation finish. + +Mutating 10_33->11_33: + Mutating: 0 + Result: 0-18 + Mutating: 0-18 + Result: 0-18 + Mutating: 0-18 + Result: 0-nthMostRecentlyUsed(0) +10_33->11_33 mutation finish. + + +Result for configuration 11x0: 22 ms +Result for configuration 11x1: 21 ms +Result for configuration 11x2: 21 ms +Result for configuration 11x3: 21 ms +Result for configuration 11x4: 21 ms +Result for configuration 11x5: 21 ms +Result for configuration 11x6: 21 ms +Result for configuration 11x7: 21 ms +Result for configuration 11x8: 21 ms +Result for configuration 11x9: 21 ms +Result for configuration 11x10: 21 ms +Result for configuration 11x11: 21 ms +Result for configuration 11x12: 21 ms +Result for configuration 11x13: 21 ms +Result for configuration 11x14: 21 ms +Result for configuration 11x15: 21 ms +Result for configuration 11x16: 20 ms +Result for configuration 11x17: 20 ms +Result for configuration 11x18: 21 ms +Result for configuration 11x19: 20 ms +Result for configuration 11x20: 20 ms +Result for configuration 11x21: 21 ms +Result for configuration 11x22: 21 ms +Result for configuration 11x23: 21 ms +Result for configuration 11x24: 21 ms +Result for configuration 11x25: 20 ms +Result for configuration 11x26: 21 ms +Result for configuration 11x27: 21 ms +Result for configuration 11x28: 21 ms +Result for configuration 11x29: 21 ms +Result for configuration 11x30: 21 ms +Result for configuration 11x31: 20 ms +Result for configuration 11x32: 20 ms +Result for configuration 11x33: 20 ms +Result for configuration 11x34: 21 ms diff --git a/dat/results/results_difffile-large.ods b/dat/results/results_difffile-large.ods new file mode 100644 index 0000000..513f2c8 Binary files /dev/null and b/dat/results/results_difffile-large.ods differ diff --git a/dat/results/results_samefile-images.ods b/dat/results/results_samefile-images.ods new file mode 100644 index 0000000..235cfc6 Binary files /dev/null and b/dat/results/results_samefile-images.ods differ diff --git a/dat/runTests.sh b/dat/runTests.sh new file mode 100644 index 0000000..25ed1ab --- /dev/null +++ b/dat/runTests.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Runs Emergen(e)tic with a series of scripts + +GEN="30" +CAN="20" + +dnc "emergenetic.dn" + +for FILE in ./scripts/*; do + FILE=${FILE##*/} + FILE=${FILE%.script} + + dana "emergenetic" $FILE $GEN $CAN + + for DIR in ./cache/*; do + (cd "$DIR" && rm *.o) + done + cd results/ && rm *.txt && cd .. + tar -jcvf ./archives/$FILE.bz2 cache + rm -R cache + cp -a ./cachebackup ./cache +done + +echo 'Complete.' >complete.txt diff --git a/dat/scripts/difffile-html.script b/dat/scripts/difffile-html.script new file mode 100644 index 0000000..5fdc7f7 --- /dev/null +++ b/dat/scripts/difffile-html.script @@ -0,0 +1,44 @@ +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index_150KB.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index_150KB.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index_150KB.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html +./htdocs/index_150KB.html +./htdocs/index.html +./htdocs/index_big.html +./htdocs/index_huge.html +./htdocs/index_med.html +./htdocs/index_small.html \ No newline at end of file diff --git a/dat/scripts/difffile-images.script b/dat/scripts/difffile-images.script new file mode 100644 index 0000000..4e79cd2 --- /dev/null +++ b/dat/scripts/difffile-images.script @@ -0,0 +1,48 @@ +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_small.jpg +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/image_med.jpg \ No newline at end of file diff --git a/dat/scripts/difffile-large.script b/dat/scripts/difffile-large.script new file mode 100644 index 0000000..a8e66fc --- /dev/null +++ b/dat/scripts/difffile-large.script @@ -0,0 +1,40 @@ +./htdocs/image_big.jpg +./htdocs/index_150KB.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_huge.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/index_150KB.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_huge.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/index_150KB.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_big.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_150KB.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_huge.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/index_150KB.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_huge.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/image_big.jpg +./htdocs/index_150KB.html +./htdocs/index_big.html +./htdocs/image_big.jpg +./htdocs/index_big.html +./htdocs/index_big.html \ No newline at end of file diff --git a/dat/scripts/difffile-small.script b/dat/scripts/difffile-small.script new file mode 100644 index 0000000..f4449ce --- /dev/null +++ b/dat/scripts/difffile-small.script @@ -0,0 +1,40 @@ +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html +./htdocs/image_small.jpg +./htdocs/index_small.html +./htdocs/index_small.html \ No newline at end of file diff --git a/dat/scripts/difffile.script b/dat/scripts/difffile.script new file mode 100644 index 0000000..ea54679 --- /dev/null +++ b/dat/scripts/difffile.script @@ -0,0 +1,40 @@ +./htdocs/image_med.jpg +./htdocs/index_150KB.html +./htdocs/index_small.html +./htdocs/image_big.jpg +./htdocs/index.html +./htdocs/index_med.html +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/index_150KB.html +./htdocs/index_small.html +./htdocs/image_big.jpg +./htdocs/index.html +./htdocs/index_med.html +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/index_150KB.html +./htdocs/index_small.html +./htdocs/image_big.jpg +./htdocs/index.html +./htdocs/index_med.html +./htdocs/image_med.jpg +./htdocs/index_150KB.html +./htdocs/index_small.html +./htdocs/image_big.jpg +./htdocs/index.html +./htdocs/index_med.html +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/index_150KB.html +./htdocs/index_small.html +./htdocs/image_big.jpg +./htdocs/index.html +./htdocs/index_med.html +./htdocs/image_small.jpg +./htdocs/image_med.jpg +./htdocs/index_150KB.html +./htdocs/index_small.html +./htdocs/image_big.jpg +./htdocs/index.html +./htdocs/index_med.html \ No newline at end of file diff --git a/dat/scripts/samefile-html.script b/dat/scripts/samefile-html.script new file mode 100644 index 0000000..54c36df --- /dev/null +++ b/dat/scripts/samefile-html.script @@ -0,0 +1,40 @@ +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html +./htdocs/index_med.html \ No newline at end of file diff --git a/dat/scripts/samefile-images.script b/dat/scripts/samefile-images.script new file mode 100644 index 0000000..4f6d56a --- /dev/null +++ b/dat/scripts/samefile-images.script @@ -0,0 +1,40 @@ +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg +./htdocs/image_med.jpg \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..0e34078 --- /dev/null +++ b/index.html @@ -0,0 +1,68 @@ +

SCC.300 Final Year Project

+ +

Contact

+ +

Ben Goldsworthy (33576556) - Email

+ +

Introduction

+ +

This is the landing page for my final year project: ‘EmerGen(e)tic: Exploring the use of genetic algorithms in distributed emergent systems’.

+ +

Abstract

+ +

“Adaptive and emergent systems exist to attempt to answer the deficiencies inherent to distributed systems, and the necessarily finite ability of any programmer to predict all possible eventualities in which his software may one day find itself. This paper argues that these systems fail to go far enough, and then proposes a further development—genetic systems—which utilises evolutionary programming to extend the versatility of a given system massively, if not infinitely. This paper proceeds to detail the EmerGen(e)tic framework for rapidly testing genetic algorithm modules within emergent systems, as well as an example module pertaining to the cache updating behaviour of a web server. This paper concludes by proposing further avenues of potentially-fruitful research based upon these programs and its findings.”

+ +

Files

+ + \ No newline at end of file diff --git a/report/final-report.aux b/report/final-report.aux new file mode 100644 index 0000000..8617c76 --- /dev/null +++ b/report/final-report.aux @@ -0,0 +1,164 @@ +\relax +\citation{distsys} +\citation{reliable} +\citation{machinecentric} +\citation{antenna} +\citation{genprog} +\citation{ants} +\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{4}} +\newlabel{sec:introduction}{{1}{4}} +\@writefile{loa}{\contentsline {algorithm}{\numberline {1}{\ignorespaces Basic genetic algorithm}}{5}} +\newlabel{alg1}{{1}{5}} +\citation{bugcost} +\citation{1000} +\citation{cni} +\citation{unix} +\citation{geometry} +\citation{email} +\citation{rfc} +\citation{distsys} +\@writefile{toc}{\contentsline {section}{\numberline {2}Background}{7}} +\newlabel{sec:background}{{2}{7}} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Assumptions}{7}} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Distributed and Adaptive Systems}{7}} +\citation{dana} +\citation{dana} +\citation{machinecentric} +\citation{machinecentric} +\citation{losingcontrol} +\citation{rex} +\citation{fusion} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Emergent Systems}{8}} +\citation{floyd} +\citation{genprog} +\citation{security} +\citation{antenna} +\citation{ants} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}`Genetic Systems'}{9}} +\@writefile{toc}{\contentsline {section}{\numberline {3}Design}{10}} +\newlabel{sec:design}{{3}{10}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}EmerGen(e)tic}{10}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}The Web Server}{10}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.1}How a web server works}{10}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.2}Added extras}{11}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.3}A tale of two web servers}{11}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Caching}{12}} +\newlabel{sec:caching}{{3.3}{12}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.4}The `Cache Policy' Genetic Algorithm}{12}} +\@writefile{toc}{\contentsline {section}{\numberline {4}Implementation: EmerGen(e)tic}{14}} +\newlabel{sec:implementation}{{4}{14}} +\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Folder Structure}{14}} +\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}\lstinline |emergenetic.dn|}{14}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.1}\lstinline |App:main()|}{14}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.2}\lstinline |runGeneration()|}{14}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.3}\lstinline |runCandidate()|}{14}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.4}\lstinline |printResults()|}{14}} +\@writefile{toc}{\contentsline {section}{\numberline {5}Implementation: \lstinline |cachingpolicy|}{15}} +\newlabel{sec:cachingpolicyimpl}{{5}{15}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Folder Structure}{15}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Genetic Algorithm search space}{15}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}\lstinline |CacheHandlerBase.dn|}{16}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.1}\lstinline |CacheHandler:getGetCachedResponse()|}{16}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.2}\lstinline |CacheHandler:updateCache()|}{16}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.3}\lstinline |CacheHandler:clearCache()|}{16}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.4}\lstinline |nthMostFrequentlyUsed()|, \lstinline |nthMostRecentlyUsed()| \& \lstinline |random()|}{16}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.5}\lstinline |resolve()|}{16}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.4}\lstinline |emergenetic.dn|}{16}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.5}\lstinline |cachingpolicy/mutator.py|}{16}} +\newlabel{sec:python}{{5.5}{16}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.1}\lstinline |getSubLists()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.2}\lstinline |crossover()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.3}\lstinline |mutate()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.4}\lstinline |parse()| \& \lstinline |compile()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.5}\lstinline |createInitialPop()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.6}\lstinline |readChromosomeFromFile()| \& \lstinline |writeChromosomeToFile()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.7}\lstinline |hasSubTrees()|}{17}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.8}\lstinline |main()|}{17}} +\@writefile{toc}{\contentsline {subsection}{\numberline {5.6}\lstinline |cachingpolicy/config.conf|}{17}} +\@writefile{toc}{\contentsline {section}{\numberline {6}The System in Operation}{18}} +\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}Creating a Module}{18}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.1}Files}{18}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.2}Implementation}{18}} +\@writefile{toc}{\contentsline {subsection}{\numberline {6.2}Creating Scripts}{18}} +\@writefile{toc}{\contentsline {subsection}{\numberline {6.3}Running EmerGen(e)tic}{18}} +\@writefile{toc}{\contentsline {subsection}{\numberline {6.4}Background Tests}{20}} +\@writefile{toc}{\contentsline {section}{\numberline {7}Testing \& Evaluation}{21}} +\newlabel{sec:testing}{{7}{21}} +\@writefile{toc}{\contentsline {subsection}{\numberline {7.1}Testing EmerGen(e)tic}{21}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/helloworld/output50.txt}{21}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/helloworld/output50.txt}{21}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/helloworld/output0.txt}{21}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/helloworld/output0.txt}{22}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/helloworld/output100.txt}{22}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/helloworld/output100.txt}{22}} +\@writefile{toc}{\contentsline {subsection}{\numberline {7.2}Testing \lstinline |cachingpolicy|}{23}} +\newlabel{sec:testingcache}{{7.2}{23}} +\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces }}{23}} +\newlabel{fig:difffile-large}{{1}{23}} +\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces }}{23}} +\newlabel{fig:difffile-large-wo}{{2}{23}} +\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces }}{23}} +\newlabel{fig:samefile-images}{{3}{23}} +\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces }}{23}} +\newlabel{fig:samefile-images-wo}{{4}{23}} +\@writefile{toc}{\contentsline {subsection}{\numberline {7.3}Evaluation}{24}} +\newlabel{sec:eval}{{7.3}{24}} +\@writefile{toc}{\contentsline {section}{\numberline {8}Conclusion}{25}} +\@writefile{toc}{\contentsline {subsection}{\numberline {8.1}Future Development}{25}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.1.1}Completing the original goal of finding the optimal conditions for the genetic algorithm}{25}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.1.2}Designing more modules}{25}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.1.3}A more `Danatically'-designed EmerGen(e)tic}{25}} +\citation{meta} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.1.4}Issues within the present \lstinline |cachingpolicy| module}{26}} +\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.1.5}Putting human developers further out of work (through meta-learning)}{26}} +\bibstyle{IEEEtran} +\bibdata{final-report} +\bibcite{distsys}{1} +\bibcite{reliable}{2} +\bibcite{machinecentric}{3} +\bibcite{antenna}{4} +\bibcite{genprog}{5} +\bibcite{ants}{6} +\bibcite{bugcost}{7} +\bibcite{1000}{8} +\bibcite{cni}{9} +\bibcite{unix}{10} +\bibcite{geometry}{11} +\bibcite{email}{12} +\bibcite{rfc}{13} +\bibcite{dana}{14} +\bibcite{losingcontrol}{15} +\bibcite{rex}{16} +\bibcite{fusion}{17} +\bibcite{floyd}{18} +\bibcite{security}{19} +\bibcite{meta}{20} +\@writefile{toc}{\contentsline {section}{References}{27}} +\@writefile{toc}{\contentsline {section}{Appendix\nobreakspace A: \lstinline |emergenetic.dn|}{28}} +\newlabel{appendix:emergen}{{A}{28}} +\@writefile{lol}{\contentsline {lstlisting}{../src/emergenetic/emergenetic.dn}{28}} +\@writefile{toc}{\contentsline {section}{Appendix\nobreakspace B: \lstinline |helloworld/mutator.py|}{32}} +\newlabel{appendix:helloworld}{{B}{32}} +\@writefile{lol}{\contentsline {lstlisting}{../src/helloworld/project/helloworld/mutator.py}{32}} +\@writefile{toc}{\contentsline {section}{Appendix\nobreakspace C: \lstinline |cachingpolicy|}{34}} +\@writefile{toc}{\contentsline {subsection}{\numberline {C.1}\lstinline |CacheHandlerBase.dn|}{34}} +\newlabel{appendix:base}{{C.1}{34}} +\@writefile{lol}{\contentsline {lstlisting}{../src/cachingpolicy/cachebackup/CacheHandlerBase.dn}{34}} +\@writefile{toc}{\contentsline {subsection}{\numberline {C.2}\lstinline |mutator.py|}{39}} +\newlabel{appendix:genetic}{{C.2}{39}} +\@writefile{lol}{\contentsline {lstlisting}{../src/cachingpolicy/project/cachingpolicy/mutator.py}{39}} +\@writefile{toc}{\contentsline {subsection}{\numberline {C.3}\lstinline |emergenetic.dn|'s \lstinline |runCandidates()| method}{44}} +\newlabel{appendix:runcand}{{C.3}{44}} +\@writefile{lol}{\contentsline {lstlisting}{../src/cachingpolicy/emergenetic.dn}{44}} +\@writefile{toc}{\contentsline {subsection}{\numberline {C.4}\lstinline |setup.sh|}{45}} +\newlabel{appendix:setup}{{C.4}{45}} +\@writefile{lol}{\contentsline {lstlisting}{../src/cachingpolicy/project/cachingpolicy/setup.sh}{45}} +\@writefile{toc}{\contentsline {subsection}{\numberline {C.5}\lstinline |config.conf|}{45}} +\newlabel{appendix:settings}{{C.5}{45}} +\@writefile{lol}{\contentsline {lstlisting}{../src/cachingpolicy/project/cachingpolicy/config.conf}{46}} +\@writefile{toc}{\contentsline {subsection}{\numberline {C.6}Gen. 18 chromosomes}{46}} +\newlabel{appendix:chromosomes}{{C.6}{46}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/cache/difffile\textendash large/17/chromosomes.txt}{46}} +\@writefile{toc}{\contentsline {section}{Appendix\nobreakspace D: \lstinline |runTests.sh|}{47}} +\newlabel{appendix:bash}{{D}{47}} +\@writefile{lol}{\contentsline {lstlisting}{../dat/runTests.sh}{47}} diff --git a/report/final-report.bbl b/report/final-report.bbl new file mode 100644 index 0000000..2287e56 --- /dev/null +++ b/report/final-report.bbl @@ -0,0 +1,130 @@ +% Generated by IEEEtran.bst, version: 1.14 (2015/08/26) +\begin{thebibliography}{10} +\providecommand{\url}[1]{#1} +\csname url@samestyle\endcsname +\providecommand{\newblock}{\relax} +\providecommand{\bibinfo}[2]{#2} +\providecommand{\BIBentrySTDinterwordspacing}{\spaceskip=0pt\relax} +\providecommand{\BIBentryALTinterwordstretchfactor}{4} +\providecommand{\BIBentryALTinterwordspacing}{\spaceskip=\fontdimen2\font plus +\BIBentryALTinterwordstretchfactor\fontdimen3\font minus + \fontdimen4\font\relax} +\providecommand{\BIBforeignlanguage}[2]{{% +\expandafter\ifx\csname l@#1\endcsname\relax +\typeout{** WARNING: IEEEtran.bst: No hyphenation pattern has been}% +\typeout{** loaded for the language `#1'. Using the pattern for}% +\typeout{** the default language instead.}% +\else +\language=\csname l@#1\endcsname +\fi +#2}} +\providecommand{\BIBdecl}{\relax} +\BIBdecl + +\bibitem{distsys} +G.~F. Coulouris, J.~Dollimore, T.~Kindberg, and G.~Blair, \emph{Distributed + Systems: Concepts and Design}, 5th~ed.\hskip 1em plus 0.5em minus 0.4em\relax + Addison-Wesley, 2012. + +\bibitem{reliable} +\BIBentryALTinterwordspacing +E.~Redwine and J.~L. Holliday, ``Reliability of distributed systems.'' + [Online]. Available: \url{http://www.cse.scu.edu/~jholliday/REL-EAR.htm} +\BIBentrySTDinterwordspacing + +\bibitem{machinecentric} +R.~Rodrigues~Filho and B.~F. Porter, ``Experiments with a machine-centric + approach to realise distributed emergent software systems,'' 2016. + +\bibitem{antenna} +G.~Hornby, A.~Globus, D.~Linden, and J.~Lohn, ``Automated antenna design with + evolutionary algorithms,'' in \emph{Space 2006}, 2015, p. 7242. + +\bibitem{genprog} +C.~Le~Goues, M.~Dewey-Vogt, S.~Forrest, and W.~Weimer, ``A systematic study of + automated program repair: Fixing 55 out of 105 bugs for \$8 each,'' in + \emph{Software Engineering (ICSE), 2012 34th International Conference + on}.\hskip 1em plus 0.5em minus 0.4em\relax IEEE, 2012, pp. 3--13. + +\bibitem{ants} +B.~Goldsworthy, ```thanks, ants. thants.': Applying genetic algorithms to + simulated ants to produce higher-fitness generations,'' unpublished. + +\bibitem{bugcost} +M.~Dawson, D.~N. Burrell, E.~Rahim, and S.~Brewster, ``Integrating software + assurance into the software development life cycle (sdlc),'' \emph{Journal of + Information Systems Technology and Planning}, vol.~3, no.~6, 2010. + +\bibitem{1000} +S.~McConnell, \emph{Code complete}.\hskip 1em plus 0.5em minus 0.4em\relax + Pearson Education, 2004. + +\bibitem{cni} +B.~Goldsworthy, ``Critical infrastructures protection: the responsibility of + government or of companies?'' unpublished. + +\bibitem{unix} +E.~S. Raymond, \emph{The art of Unix programming}.\hskip 1em plus 0.5em minus + 0.4em\relax Addison-Wesley Professional, 2003. + +\bibitem{geometry} +D.~Muder, \emph{The Unreasonable Influence of Geometry}, 2000. + +\bibitem{email} +\BIBentryALTinterwordspacing +L.~Lamport, ``Distribution,'' May 1987. [Online]. Available: + \url{https://www.microsoft.com/en-us/research/publication/distribution/} +\BIBentrySTDinterwordspacing + +\bibitem{rfc} +\BIBentryALTinterwordspacing +S.~Crocker, ``New host-host protocol,'' Internet Requests for Comments, RFC + Editor, RFC~33, February 1970, \url{http://www.rfc-editor.org/rfc/rfc33.txt}. + [Online]. Available: \url{http://www.rfc-editor.org/rfc/rfc33.txt} +\BIBentrySTDinterwordspacing + +\bibitem{dana} +B.~F. Porter, ``Runtime modularity in complex structures: A component model for + fine grained runtime adaptation,'' in \emph{Proceedings of the 17th + international ACM Sigsoft symposium on Component-based software + engineering}.\hskip 1em plus 0.5em minus 0.4em\relax ACM, 2014, pp. 29--34. + +\bibitem{losingcontrol} +B.~F. Porter and R.~Rodrigues~Filho, ``Losing control: The case for emergent + software systems using autonomous assembly, perception, and learning,'' in + \emph{Self-Adaptive and Self-Organizing Systems (SASO), 2016 IEEE 10th + International Conference on}.\hskip 1em plus 0.5em minus 0.4em\relax IEEE, + 2016, pp. 40--49. + +\bibitem{rex} +B.~Porter, M.~Grieves, R.~Rodrigues~Filho, and D.~Leslie, ``Re$^{\text{x}}$: A + development platform and online learning approach for runtime emergent + software systems,'' in \emph{Proceedings of the 12th USENIX Symposium on + Operating Systems Design and Implementation. USENIX}, 2016. + +\bibitem{fusion} +\BIBentryALTinterwordspacing +A.~Elkhodary, N.~Esfahani, and S.~Malek, ``Fusion: A framework for engineering + self-tuning self-adaptive software systems,'' in \emph{Proceedings of the + Eighteenth ACM SIGSOFT International Symposium on Foundations of Software + Engineering}, ser. FSE '10.\hskip 1em plus 0.5em minus 0.4em\relax New York, + NY, USA: ACM, 2010, pp. 7--16. [Online]. Available: + \url{http://doi.acm.org/10.1145/1882291.1882296} +\BIBentrySTDinterwordspacing + +\bibitem{floyd} +R.~W. Floyd, ``The paradigms of programming,'' \emph{Communications of the + ACM}, vol.~22, no.~8, pp. 455--460, 1979. + +\bibitem{security} +J.~V. Hansen, P.~B. Lowry, R.~D. Meservy, and D.~M. McDonald, ``Genetic + programming for prevention of cyberterrorism through dynamic and evolving + intrusion detection,'' \emph{Decision Support Systems}, vol.~43, no.~4, pp. + 1362--1374, 2007. + +\bibitem{meta} +J.~Schmidhuber, ``Evolutionary principles in self-referential learning,'' + \emph{On learning how to learn: The meta-meta-... hook.) Diploma thesis, + Institut f. Informatik, Tech. Univ. Munich}, 1987. + +\end{thebibliography} diff --git a/report/final-report.bib b/report/final-report.bib new file mode 100644 index 0000000..a43baf5 --- /dev/null +++ b/report/final-report.bib @@ -0,0 +1,193 @@ +@IEEEtranBSTCTL{IEEEexample:BSTcontrol, +CTLdash_repeated_names = "no", +} + +@incollection{antenna, + title={Automated antenna design with evolutionary algorithms}, + author={Hornby, Gregory and Globus, Al and Linden, Derek and Lohn, Jason}, + booktitle={Space 2006}, + pages={7242}, + year={2015} +} + +@inproceedings{genprog, + title={A systematic study of automated program repair: Fixing 55 out of 105 bugs for \$8 each}, + author={Le Goues, Claire and Dewey-Vogt, Michael and Forrest, Stephanie and Weimer, Westley}, + booktitle={Software Engineering (ICSE), 2012 34th International Conference on}, + pages={3--13}, + year={2012}, + organization={IEEE} +} + +@article{ants, + title={`Thanks, ants. Thants.': Applying genetic algorithms to simulated ants to produce higher-fitness generations}, + author={Ben Goldsworthy}, + year={unpublished} +} + +@inproceedings{dana, + title={Runtime modularity in complex structures: A component model for fine grained runtime adaptation}, + author={Porter, Barry Francis}, + booktitle={Proceedings of the 17th international ACM Sigsoft symposium on Component-based software engineering}, + pages={29--34}, + year={2014}, + organization={ACM} +} + +@article{machinecentric, + title={Experiments with a machine-centric approach to realise distributed emergent software systems}, + author={Rodrigues Filho, Roberto and Porter, Barry Francis}, + year={2016}, + publisher={ACM} +} + +@article{meta, + title={Evolutionary principles in self-referential learning}, + author={Schmidhuber, Jurgen}, + journal={On learning how to learn: The meta-meta-... hook.) Diploma thesis, Institut f. Informatik, Tech. Univ. Munich}, + year={1987} +} + +@book{distsys, + author={Coulouris, George F and Dollimore, Jean and Kindberg, Tim and Blair, Gordon}, + title={Distributed Systems: Concepts and Design}, + place={Boston, Mass.}, + edition={5}, + publisher={Addison-Wesley}, + year={2012} +} + +@misc{reliable, + author={Redwine, Erick and Holliday, JoAnne L}, + title={Reliability of Distributed Systems}, + url={http://www.cse.scu.edu/~jholliday/REL-EAR.htm}, + urldate={2017-3-2}, + journal={Cse.scu.edu} +} + +@inproceedings{losingcontrol, + title={Losing Control: The Case for Emergent Software Systems Using Autonomous Assembly, Perception, and Learning}, + author={Porter, Barry Francis and Rodrigues Filho, Roberto}, + booktitle={Self-Adaptive and Self-Organizing Systems (SASO), 2016 IEEE 10th International Conference on}, + pages={40--49}, + year={2016}, + organization={IEEE} +} + +@inproceedings{rex, + title={RE$^{\text{X}}$: A development platform and online learning approach for runtime emergent software systems}, + author={Porter, Barry and Grieves, Matthew and Rodrigues Filho, Roberto and Leslie, David}, + booktitle={Proceedings of the 12th USENIX Symposium on Operating Systems Design and Implementation. USENIX}, + year={2016} +} + +@inproceedings{fusion, + author = {Elkhodary, Ahmed and Esfahani, Naeem and Malek, Sam}, + title = {FUSION: A Framework for Engineering Self-tuning Self-adaptive Software Systems}, + booktitle = {Proceedings of the Eighteenth ACM SIGSOFT International Symposium on Foundations of Software Engineering}, + series = {FSE '10}, + year = {2010}, + isbn = {978-1-60558-791-2}, + location = {Santa Fe, New Mexico, USA}, + pages = {7--16}, + numpages = {10}, + url = {http://doi.acm.org/10.1145/1882291.1882296}, + doi = {10.1145/1882291.1882296}, + acmid = {1882296}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {feature-orientation, learning, qos analysis, self-adaptation}, +} + +@article{bugcost, + title={Integrating Software Assurance into the Software Development Life Cycle (SDLC)}, + author={Dawson, Maurice and Burrell, Darrell N and Rahim, Emad and Brewster, Stephen}, + journal={Journal of Information Systems Technology and Planning}, + volume={3}, + number={6}, + year={2010} +} + +@book{1000, + title={Code complete}, + author={McConnell, Steve}, + year={2004}, + publisher={Pearson Education} +} + +@book{geometry, + title={The Unreasonable Influence of Geometry}, + author={Muder, Doug}, + year={2000} +} + +@techreport{RFC, + author = {S.D. Crocker}, + title = {New Host-Host Protocol}, + howpublished = {Internet Requests for Comments}, + type = {RFC}, + number = {33}, + year = {1970}, + month = {February}, + issn = {2070-1721}, + publisher = {RFC Editor}, + institution = {RFC Editor}, + url = {http://www.rfc-editor.org/rfc/rfc33.txt}, + note = {\url{http://www.rfc-editor.org/rfc/rfc33.txt}}, +} + +@other{email, +author = {Lamport, Leslie}, +title = {Distribution}, +booktitle = {}, +year = {1987}, +month = {May}, +abstract = {This message is the source of the following observation, which has been quoted (and misquoted) rather widely: + +A distributed system is one in which the failure of a computer you didn't even know existed can render your own computer unusable. +}, +publisher = {}, +url = {https://www.microsoft.com/en-us/research/publication/distribution/}, +address = {}, +pages = {}, +journal = {}, +volume = {}, +chapter = {}, +isbn = {}, +} + +@article{floyd, + title={The paradigms of programming}, + author={Floyd, Robert W}, + journal={Communications of the ACM}, + volume={22}, + number={8}, + pages={455--460}, + year={1979}, + publisher={ACM} +} + +@article{cni, + title={Critical infrastructures protection: the responsibility of Government or of companies?}, + author={Goldsworthy, Ben}, + year={unpublished} +} + +@book{unix, + title={The art of Unix programming}, + author={Raymond, Eric S}, + year={2003}, + publisher={Addison-Wesley Professional} +} + +@article{security, + title={Genetic programming for prevention of cyberterrorism through dynamic and evolving intrusion detection}, + author={Hansen, James V and Lowry, Paul Benjamin and Meservy, Rayman D and McDonald, Daniel M}, + journal={Decision Support Systems}, + volume={43}, + number={4}, + pages={1362--1374}, + year={2007}, + publisher={Elsevier} +} + diff --git a/report/final-report.blg b/report/final-report.blg new file mode 100644 index 0000000..fc2a560 --- /dev/null +++ b/report/final-report.blg @@ -0,0 +1,15 @@ +This is BibTeX, Version 0.99dThe top-level auxiliary file: final-report.aux +The style file: IEEEtran.bst +Database file #1: final-report.bib +Warning--entry type for "email" isn't style-file defined +--line 139 of file final-report.bib +-- IEEEtran.bst version 1.14 (2015/08/26) by Michael Shell. +-- http://www.michaelshell.org/tex/ieeetran/bibtex/ +-- See the "IEEEtran_bst_HOWTO.pdf" manual for usage information. +Warning--empty journal in machinecentric +Warning--empty journal in ants +Warning--empty journal in cni +Warning--missing publisher in geometry + +Done. +(There were 5 warnings) diff --git a/report/final-report.log b/report/final-report.log new file mode 100644 index 0000000..a8c5c69 --- /dev/null +++ b/report/final-report.log @@ -0,0 +1,1203 @@ +This is pdfTeX, Version 3.1415926-2.5-1.40.14 (MiKTeX 2.9) (preloaded format=pdflatex 2014.8.24) 22 MAR 2017 11:21 +entering extended mode +**Z:/scc300/report/final-report.tex +(Z:/scc300/report/final-report.tex +LaTeX2e <2011/06/27> +Babel and hyphenation patterns for english, afrikaans, ancientgreek, ar +abic, armenian, assamese, basque, bengali, bokmal, bulgarian, catalan, coptic, +croatian, czech, danish, dutch, esperanto, estonian, farsi, finnish, french, ga +lician, german, german-x-2013-05-26, greek, gujarati, hindi, hungarian, iceland +ic, indonesian, interlingua, irish, italian, kannada, kurmanji, latin, latvian, + lithuanian, malayalam, marathi, mongolian, mongolianlmc, monogreek, ngerman, n +german-x-2013-05-26, nynorsk, oriya, panjabi, pinyin, polish, portuguese, roman +ian, russian, sanskrit, serbian, slovak, slovenian, spanish, swedish, swissgerm +an, tamil, telugu, turkish, turkmen, ukenglish, ukrainian, uppersorbian, usengl +ishmax, welsh, loaded. +("C:\Program Files (x86)\MiKTeX\tex\latex\ieeetran\IEEEtran.cls" +Document Class: IEEEtran 2015/08/26 V1.8b by Michael Shell +-- See the "IEEEtran_HOWTO" manual for usage information. +-- http://www.michaelshell.org/tex/ieeetran/ +\@IEEEtrantmpdimenA=\dimen102 +\@IEEEtrantmpdimenB=\dimen103 +\@IEEEtrantmpdimenC=\dimen104 +\@IEEEtrantmpcountA=\count79 +\@IEEEtrantmpcountB=\count80 +\@IEEEtrantmpcountC=\count81 +\@IEEEtrantmptoksA=\toks14 +LaTeX Font Info: Try loading font information for OT1+ppl on input line 503. + +("C:\Program Files (x86)\MiKTeX\tex\latex\psnfss\ot1ppl.fd" +File: ot1ppl.fd 2001/06/04 font definitions for OT1/ppl. +) +-- Using IEEE Computer Society mode. +-- Using 210mm x 297mm (a4) paper. +-- Using PDF output. +\@IEEEnormalsizeunitybaselineskip=\dimen105 +-- This is a 12 point document. +\CLASSINFOnormalsizebaselineskip=\dimen106 +\CLASSINFOnormalsizeunitybaselineskip=\dimen107 +\IEEEnormaljot=\dimen108 +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <6.02249> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <6.02249> not available +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <8.03> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <8.03> not available +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <9.03374> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <9.03374> not available +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <10.03749> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <10.03749> not available + +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <12.045> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <12.045> not available +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <14.05249> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <14.05249> not available + +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <20.075> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <20.075> not available +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <22.08249> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <22.08249> not available + +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +LaTeX Font Info: Font shape `OT1/ppl/bx/n' in size <24.09> not available +(Font) Font shape `OT1/ppl/b/n' tried instead on input line 1090. +LaTeX Font Info: Font shape `OT1/ppl/bx/it' in size <24.09> not available +(Font) Font shape `OT1/ppl/b/it' tried instead on input line 1090. + +\IEEEquantizedlength=\dimen109 +\IEEEquantizedlengthdiff=\dimen110 +\IEEEquantizedtextheightdiff=\dimen111 +\IEEEilabelindentA=\dimen112 +\IEEEilabelindentB=\dimen113 +\IEEEilabelindent=\dimen114 +\IEEEelabelindent=\dimen115 +\IEEEdlabelindent=\dimen116 +\IEEElabelindent=\dimen117 +\IEEEiednormlabelsep=\dimen118 +\IEEEiedmathlabelsep=\dimen119 +\IEEEiedtopsep=\skip41 +\c@section=\count82 +\c@subsection=\count83 +\c@subsubsection=\count84 +\c@paragraph=\count85 +\c@IEEEsubequation=\count86 +\abovecaptionskip=\skip42 +\belowcaptionskip=\skip43 +\c@figure=\count87 +\c@table=\count88 +\@IEEEeqnnumcols=\count89 +\@IEEEeqncolcnt=\count90 +\@IEEEsubeqnnumrollback=\count91 +\@IEEEquantizeheightA=\dimen120 +\@IEEEquantizeheightB=\dimen121 +\@IEEEquantizeheightC=\dimen122 +\@IEEEquantizeprevdepth=\dimen123 +\@IEEEquantizemultiple=\count92 +\@IEEEquantizeboxA=\box26 +\@IEEEtmpitemindent=\dimen124 +\IEEEPARstartletwidth=\dimen125 +\c@IEEEbiography=\count93 +\@IEEEtranrubishbin=\box27 +) ("C:\Program Files (x86)\MiKTeX\tex\latex\blindtext\blindtext.sty" +Package: blindtext 2012/01/06 V2.0 blindtext-Package + +("C:\Program Files (x86)\MiKTeX\tex\latex\tools\xspace.sty" +Package: xspace 2009/10/20 v1.13 Space after command names (DPC,MH) +) +\c@blindtext=\count94 +\c@Blindtext=\count95 +\c@blind@countparstart=\count96 +\blind@countxx=\count97 +\blindtext@numBlindtext=\count98 +\blind@countyy=\count99 +\c@blindlist=\count100 +\c@blindlistlevel=\count101 +\c@blindlist@level=\count102 +\blind@listitem=\count103 +\c@blind@listcount=\count104 +\c@blind@levelcount=\count105 +\blind@mathformula=\count106 +\blind@Mathformula=\count107 +\c@blind@randomcount=\count108 +\c@blind@randommax=\count109 +\c@blind@pangramcount=\count110 +\c@blind@pangrammax=\count111 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\graphics\color.sty" +Package: color 2005/11/14 v1.0j Standard LaTeX Color (DPC) + +("C:\Program Files (x86)\MiKTeX\tex\latex\00miktex\color.cfg" +File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive +) +Package color Info: Driver file: pdftex.def on input line 130. + +("C:\Program Files (x86)\MiKTeX\tex\latex\pdftex-def\pdftex.def" +File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX + +("C:\Program Files (x86)\MiKTeX\tex\generic\oberdiek\infwarerr.sty" +Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO) +) +("C:\Program Files (x86)\MiKTeX\tex\generic\oberdiek\ltxcmds.sty" +Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO) +) +\Gread@gobject=\count112 +)) +("C:\Program Files (x86)\MiKTeX\tex\latex\geometry\geometry.sty" +Package: geometry 2010/09/12 v5.6 Page Geometry + +("C:\Program Files (x86)\MiKTeX\tex\latex\graphics\keyval.sty" +Package: keyval 1999/03/16 v1.13 key=value parser (DPC) +\KV@toks@=\toks15 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\oberdiek\ifpdf.sty" +Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO) +Package ifpdf Info: pdfTeX in PDF mode is detected. +) +("C:\Program Files (x86)\MiKTeX\tex\generic\oberdiek\ifvtex.sty" +Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO) +Package ifvtex Info: VTeX not detected. +) +("C:\Program Files (x86)\MiKTeX\tex\generic\ifxetex\ifxetex.sty" +Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional +) +\Gm@cnth=\count113 +\Gm@cntv=\count114 +\c@Gm@tempcnt=\count115 +\Gm@bindingoffset=\dimen126 +\Gm@wd@mp=\dimen127 +\Gm@odd@mp=\dimen128 +\Gm@even@mp=\dimen129 +\Gm@layoutwidth=\dimen130 +\Gm@layoutheight=\dimen131 +\Gm@layouthoffset=\dimen132 +\Gm@layoutvoffset=\dimen133 +\Gm@dimlist=\toks16 + +("C:\Program Files (x86)\MiKTeX\tex\latex\geometry\geometry.cfg")) +("C:\Program Files (x86)\MiKTeX\tex\latex\graphics\graphicx.sty" +Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR) + +("C:\Program Files (x86)\MiKTeX\tex\latex\graphics\graphics.sty" +Package: graphics 2009/02/05 v1.0o Standard LaTeX Graphics (DPC,SPQR) + +("C:\Program Files (x86)\MiKTeX\tex\latex\graphics\trig.sty" +Package: trig 1999/03/16 v1.09 sin cos tan (DPC) +) +("C:\Program Files (x86)\MiKTeX\tex\latex\00miktex\graphics.cfg" +File: graphics.cfg 2007/01/18 v1.5 graphics configuration of teTeX/TeXLive +) +Package graphics Info: Driver file: pdftex.def on input line 91. +) +\Gin@req@height=\dimen134 +\Gin@req@width=\dimen135 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\listings\listings.sty" +\lst@mode=\count116 +\lst@gtempboxa=\box28 +\lst@token=\toks17 +\lst@length=\count117 +\lst@currlwidth=\dimen136 +\lst@column=\count118 +\lst@pos=\count119 +\lst@lostspace=\dimen137 +\lst@width=\dimen138 +\lst@newlines=\count120 +\lst@lineno=\count121 +\lst@maxwidth=\dimen139 + +("C:\Program Files (x86)\MiKTeX\tex\latex\listings\lstmisc.sty" +File: lstmisc.sty 2014/09/06 1.5e (Carsten Heinz) +\c@lstnumber=\count122 +\lst@skipnumbers=\count123 +\lst@framebox=\box29 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\listings\listings.cfg" +File: listings.cfg 2014/09/06 1.5e listings configuration +)) +Package: listings 2014/09/06 1.5e (Carsten Heinz) + +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\frontendlayer\tikz.sty" +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\basiclayer\pgf.sty" +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\utilities\pgfrcs.sty" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfutil-common.tex" +\pgfutil@everybye=\toks18 +\pgfutil@tempdima=\dimen140 +\pgfutil@tempdimb=\dimen141 + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfutil-common-lists. +tex")) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfutil-latex.def" +\pgfutil@abb=\box30 + +("C:\Program Files (x86)\MiKTeX\tex\latex\ms\everyshi.sty" +Package: everyshi 2001/05/15 v3.00 EveryShipout Package (MS) +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfrcs.code.tex" +Package: pgfrcs 2013/12/20 v3.0.0 (rcs-revision 1.28) +)) +Package: pgf 2013/12/18 v3.0.0 (rcs-revision 1.14) + +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\basiclayer\pgfcore.sty" +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\systemlayer\pgfsys.sty" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\systemlayer\pgfsys.code.tex" +Package: pgfsys 2013/11/30 v3.0.0 (rcs-revision 1.47) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfkeys.code.tex" +\pgfkeys@pathtoks=\toks19 +\pgfkeys@temptoks=\toks20 + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfkeysfiltered.code. +tex" +\pgfkeys@tmptoks=\toks21 +)) +\pgf@x=\dimen142 +\pgf@y=\dimen143 +\pgf@xa=\dimen144 +\pgf@ya=\dimen145 +\pgf@xb=\dimen146 +\pgf@yb=\dimen147 +\pgf@xc=\dimen148 +\pgf@yc=\dimen149 +\w@pgf@writea=\write3 +\r@pgf@reada=\read1 +\c@pgf@counta=\count124 +\c@pgf@countb=\count125 +\c@pgf@countc=\count126 +\c@pgf@countd=\count127 +\t@pgf@toka=\toks22 +\t@pgf@tokb=\toks23 +\t@pgf@tokc=\toks24 + ("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\systemlayer\pgf.cfg" +File: pgf.cfg 2008/05/14 (rcs-revision 1.7) +) +Driver file for pgf: pgfsys-pdftex.def + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\systemlayer\pgfsys-pdftex.def" +File: pgfsys-pdftex.def 2013/07/18 (rcs-revision 1.33) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\systemlayer\pgfsys-common-pdf.d +ef" +File: pgfsys-common-pdf.def 2013/10/10 (rcs-revision 1.13) +))) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\systemlayer\pgfsyssoftpath.code +.tex" +File: pgfsyssoftpath.code.tex 2013/09/09 (rcs-revision 1.9) +\pgfsyssoftpath@smallbuffer@items=\count128 +\pgfsyssoftpath@bigbuffer@items=\count129 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\systemlayer\pgfsysprotocol.code +.tex" +File: pgfsysprotocol.code.tex 2006/10/16 (rcs-revision 1.4) +)) ("C:\Program Files (x86)\MiKTeX\tex\latex\xcolor\xcolor.sty" +Package: xcolor 2007/01/21 v2.11 LaTeX color extensions (UK) + +("C:\Program Files (x86)\MiKTeX\tex\latex\00miktex\color.cfg" +File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive +) +Package xcolor Info: Driver file: pdftex.def on input line 225. +LaTeX Info: Redefining \color on input line 702. +Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1337. +Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1341. +Package xcolor Info: Model `RGB' extended on input line 1353. +Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1355. +Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1356. +Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1357. +Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1358. +Package xcolor Info: Model `Gray' substituted by `gray' on input line 1359. +Package xcolor Info: Model `wave' substituted by `hsb' on input line 1360. +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcore.code.tex" +Package: pgfcore 2010/04/11 v3.0.0 (rcs-revision 1.7) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmath.code.tex" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathcalc.code.tex" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathutil.code.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathparser.code.tex" +\pgfmath@dimen=\dimen150 +\pgfmath@count=\count130 +\pgfmath@box=\box31 +\pgfmath@toks=\toks25 +\pgfmath@stack@operand=\toks26 +\pgfmath@stack@operation=\toks27 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.code.tex" + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.basic.cod +e.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.trigonome +tric.code.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.random.co +de.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.compariso +n.code.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.base.code +.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.round.cod +e.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.misc.code +.tex") +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfunctions.integerar +ithmetics.code.tex"))) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmathfloat.code.tex" +\c@pgfmathroundto@lastzeros=\count131 +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorepoints.code.t +ex" +File: pgfcorepoints.code.tex 2013/10/07 (rcs-revision 1.27) +\pgf@picminx=\dimen151 +\pgf@picmaxx=\dimen152 +\pgf@picminy=\dimen153 +\pgf@picmaxy=\dimen154 +\pgf@pathminx=\dimen155 +\pgf@pathmaxx=\dimen156 +\pgf@pathminy=\dimen157 +\pgf@pathmaxy=\dimen158 +\pgf@xx=\dimen159 +\pgf@xy=\dimen160 +\pgf@yx=\dimen161 +\pgf@yy=\dimen162 +\pgf@zx=\dimen163 +\pgf@zy=\dimen164 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorepathconstruct +.code.tex" +File: pgfcorepathconstruct.code.tex 2013/10/07 (rcs-revision 1.29) +\pgf@path@lastx=\dimen165 +\pgf@path@lasty=\dimen166 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorepathusage.cod +e.tex" +File: pgfcorepathusage.code.tex 2013/12/13 (rcs-revision 1.23) +\pgf@shorten@end@additional=\dimen167 +\pgf@shorten@start@additional=\dimen168 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorescopes.code.t +ex" +File: pgfcorescopes.code.tex 2013/10/09 (rcs-revision 1.44) +\pgfpic=\box32 +\pgf@hbox=\box33 +\pgf@layerbox@main=\box34 +\pgf@picture@serial@count=\count132 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoregraphicstate. +code.tex" +File: pgfcoregraphicstate.code.tex 2013/09/19 (rcs-revision 1.11) +\pgflinewidth=\dimen169 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoretransformatio +ns.code.tex" +File: pgfcoretransformations.code.tex 2013/10/10 (rcs-revision 1.17) +\pgf@pt@x=\dimen170 +\pgf@pt@y=\dimen171 +\pgf@pt@temp=\dimen172 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorequick.code.te +x" +File: pgfcorequick.code.tex 2008/10/09 (rcs-revision 1.3) +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoreobjects.code. +tex" +File: pgfcoreobjects.code.tex 2006/10/11 (rcs-revision 1.2) +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorepathprocessin +g.code.tex" +File: pgfcorepathprocessing.code.tex 2013/09/09 (rcs-revision 1.9) +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorearrows.code.t +ex" +File: pgfcorearrows.code.tex 2013/11/07 (rcs-revision 1.40) +\pgfarrowsep=\dimen173 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoreshade.code.te +x" +File: pgfcoreshade.code.tex 2013/07/15 (rcs-revision 1.15) +\pgf@max=\dimen174 +\pgf@sys@shading@range@num=\count133 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoreimage.code.te +x" +File: pgfcoreimage.code.tex 2013/07/15 (rcs-revision 1.18) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoreexternal.code +.tex" +File: pgfcoreexternal.code.tex 2013/07/15 (rcs-revision 1.20) +\pgfexternal@startupbox=\box35 +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorelayers.code.t +ex" +File: pgfcorelayers.code.tex 2013/07/18 (rcs-revision 1.7) +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcoretransparency. +code.tex" +File: pgfcoretransparency.code.tex 2013/09/30 (rcs-revision 1.5) +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\basiclayer\pgfcorepatterns.code +.tex" +File: pgfcorepatterns.code.tex 2013/11/07 (rcs-revision 1.5) +))) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\modules\pgfmoduleshapes.code.te +x" +File: pgfmoduleshapes.code.tex 2013/10/31 (rcs-revision 1.34) +\pgfnodeparttextbox=\box36 +) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\modules\pgfmoduleplot.code.tex" +File: pgfmoduleplot.code.tex 2013/07/31 (rcs-revision 1.12) +) +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\compatibility\pgfcomp-version-0-6 +5.sty" +Package: pgfcomp-version-0-65 2007/07/03 v3.0.0 (rcs-revision 1.7) +\pgf@nodesepstart=\dimen175 +\pgf@nodesepend=\dimen176 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\compatibility\pgfcomp-version-1-1 +8.sty" +Package: pgfcomp-version-1-18 2007/07/23 v3.0.0 (rcs-revision 1.1) +)) ("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\utilities\pgffor.sty" +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\utilities\pgfkeys.sty" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgfkeys.code.tex")) +("C:\Program Files (x86)\MiKTeX\tex\latex\pgf\math\pgfmath.sty" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmath.code.tex")) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\utilities\pgffor.code.tex" +Package: pgffor 2013/12/13 v3.0.0 (rcs-revision 1.25) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\math\pgfmath.code.tex") +\pgffor@iter=\dimen177 +\pgffor@skip=\dimen178 +\pgffor@stack=\toks28 +\pgffor@toks=\toks29 +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\tikz.code.te +x" +Package: tikz 2013/12/13 v3.0.0 (rcs-revision 1.142) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\pgflibraryplothandler +s.code.tex" +File: pgflibraryplothandlers.code.tex 2013/08/31 v3.0.0 (rcs-revision 1.20) +\pgf@plot@mark@count=\count134 +\pgfplotmarksize=\dimen179 +) +\tikz@lastx=\dimen180 +\tikz@lasty=\dimen181 +\tikz@lastxsaved=\dimen182 +\tikz@lastysaved=\dimen183 +\tikzleveldistance=\dimen184 +\tikzsiblingdistance=\dimen185 +\tikz@figbox=\box37 +\tikz@figbox@bg=\box38 +\tikz@tempbox=\box39 +\tikz@tempbox@bg=\box40 +\tikztreelevel=\count135 +\tikznumberofchildren=\count136 +\tikznumberofcurrentchild=\count137 +\tikz@fig@count=\count138 + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\modules\pgfmodulematrix.code.te +x" +File: pgfmodulematrix.code.tex 2013/09/17 (rcs-revision 1.8) +\pgfmatrixcurrentrow=\count139 +\pgfmatrixcurrentcolumn=\count140 +\pgf@matrix@numberofcolumns=\count141 +) +\tikz@expandcount=\count142 + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibrarytopaths.code.tex" +File: tikzlibrarytopaths.code.tex 2008/06/17 v3.0.0 (rcs-revision 1.2) +))) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.code.tex" +File: tikzlibraryshapes.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.geometric.code.tex" +File: tikzlibraryshapes.geometric.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\shapes\pgflibraryshap +es.geometric.code.tex" +File: pgflibraryshapes.geometric.code.tex 2008/06/26 v3.0.0 (rcs-revision 1.1) +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.misc.code.tex" +File: tikzlibraryshapes.misc.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\shapes\pgflibraryshap +es.misc.code.tex" +File: pgflibraryshapes.misc.code.tex 2013/07/18 v3.0.0 (rcs-revision 1.5) +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.symbols.code.tex" +File: tikzlibraryshapes.symbols.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\shapes\pgflibraryshap +es.symbols.code.tex" +File: pgflibraryshapes.symbols.code.tex 2013/09/11 v3.0.0 (rcs-revision 1.6) +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.arrows.code.tex" +File: tikzlibraryshapes.arrows.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\shapes\pgflibraryshap +es.arrows.code.tex" +File: pgflibraryshapes.arrows.code.tex 2008/06/26 v3.0.0 (rcs-revision 1.1) +)) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.callouts.code.tex" +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\shapes\pgflibraryshap +es.callouts.code.tex")) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryshapes.multipart.code.tex" +File: tikzlibraryshapes.multipart.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\shapes\pgflibraryshap +es.multipart.code.tex" +File: pgflibraryshapes.multipart.code.tex 2010/01/07 v3.0.0 (rcs-revision 1.2) +\pgfnodepartlowerbox=\box41 +\pgfnodeparttwobox=\box42 +\pgfnodepartthreebox=\box43 +\pgfnodepartfourbox=\box44 +\pgfnodeparttwentybox=\box45 +\pgfnodepartnineteenbox=\box46 +\pgfnodeparteighteenbox=\box47 +\pgfnodepartseventeenbox=\box48 +\pgfnodepartsixteenbox=\box49 +\pgfnodepartfifteenbox=\box50 +\pgfnodepartfourteenbox=\box51 +\pgfnodepartthirteenbox=\box52 +\pgfnodeparttwelvebox=\box53 +\pgfnodepartelevenbox=\box54 +\pgfnodeparttenbox=\box55 +\pgfnodepartninebox=\box56 +\pgfnodeparteightbox=\box57 +\pgfnodepartsevenbox=\box58 +\pgfnodepartsixbox=\box59 +\pgfnodepartfivebox=\box60 +))) +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\frontendlayer\tikz\libraries\ti +kzlibraryarrows.code.tex" +File: tikzlibraryarrows.code.tex 2008/01/09 v3.0.0 (rcs-revision 1.1) + +("C:\Program Files (x86)\MiKTeX\tex\generic\pgf\libraries\pgflibraryarrows.code +.tex" +File: pgflibraryarrows.code.tex 2013/09/23 v3.0.0 (rcs-revision 1.16) +\arrowsize=\dimen186 +)) ("C:\Program Files (x86)\MiKTeX\tex\latex\wrapfig\wrapfig.sty" +\wrapoverhang=\dimen187 +\WF@size=\dimen188 +\c@WF@wrappedlines=\count143 +\WF@box=\box61 +\WF@everypar=\toks30 +Package: wrapfig 2003/01/31 v 3.6 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\cite\cite.sty" +LaTeX Info: Redefining \cite on input line 302. +LaTeX Info: Redefining \nocite on input line 332. +Package: cite 2015/02/27 v 5.5 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\amsmath\amsmath.sty" +Package: amsmath 2013/01/14 v2.14 AMS math features +\@mathmargin=\skip44 + +For additional information on amsmath, use the `?' option. +("C:\Program Files (x86)\MiKTeX\tex\latex\amsmath\amstext.sty" +Package: amstext 2000/06/29 v2.01 + +("C:\Program Files (x86)\MiKTeX\tex\latex\amsmath\amsgen.sty" +File: amsgen.sty 1999/11/30 v2.0 +\@emptytoks=\toks31 +\ex@=\dimen189 +)) +("C:\Program Files (x86)\MiKTeX\tex\latex\amsmath\amsbsy.sty" +Package: amsbsy 1999/11/29 v1.2d +\pmbraise@=\dimen190 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\amsmath\amsopn.sty" +Package: amsopn 1999/12/14 v2.01 operator names +) +\inf@bad=\count144 +LaTeX Info: Redefining \frac on input line 210. +\uproot@=\count145 +\leftroot@=\count146 +LaTeX Info: Redefining \overline on input line 306. +\classnum@=\count147 +\DOTSCASE@=\count148 +LaTeX Info: Redefining \ldots on input line 378. +LaTeX Info: Redefining \dots on input line 381. +LaTeX Info: Redefining \cdots on input line 466. +\Mathstrutbox@=\box62 +\strutbox@=\box63 +\big@size=\dimen191 +LaTeX Font Info: Redeclaring font encoding OML on input line 566. +LaTeX Font Info: Redeclaring font encoding OMS on input line 567. +\macc@depth=\count149 +\c@MaxMatrixCols=\count150 +\dotsspace@=\muskip10 +\c@parentequation=\count151 +\dspbrk@lvl=\count152 +\tag@help=\toks32 +\row@=\count153 +\column@=\count154 +\maxfields@=\count155 +\andhelp@=\toks33 +\eqnshift@=\dimen192 +\alignsep@=\dimen193 +\tagshift@=\dimen194 +\tagwidth@=\dimen195 +\totwidth@=\dimen196 +\lineht@=\dimen197 +\@envbody=\toks34 +\multlinegap=\skip45 +\multlinetaggap=\skip46 +\mathdisplay@stack=\toks35 +LaTeX Info: Redefining \[ on input line 2665. +LaTeX Info: Redefining \] on input line 2666. +) +("C:\Program Files (x86)\MiKTeX\tex\latex\algorithms\algorithm.sty" +Package: algorithm 2009/08/24 v0.1 Document Style `algorithm' - floating enviro +nment + +("C:\Program Files (x86)\MiKTeX\tex\latex\float\float.sty" +Package: float 2001/11/08 v1.3d Float enhancements (AL) +\c@float@type=\count156 +\float@exts=\toks36 +\float@box=\box64 +\@float@everytoks=\toks37 +\@floatcapt=\box65 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\base\ifthen.sty" +Package: ifthen 2001/05/26 v1.1c Standard LaTeX ifthen package (DPC) +) +\@float@every@algorithm=\toks38 +\c@algorithm=\count157 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\algorithms\algorithmic.sty" +Package: algorithmic 2009/08/24 v0.1 Document Style `algorithmic' +\c@ALC@unique=\count158 +\c@ALC@line=\count159 +\c@ALC@rem=\count160 +\c@ALC@depth=\count161 +\ALC@tlm=\skip47 +\algorithmicindent=\skip48 +) +("C:\Program Files (x86)\MiKTeX\tex\latex\amsfonts\amssymb.sty" +Package: amssymb 2013/01/14 v3.01 AMS font symbols + +("C:\Program Files (x86)\MiKTeX\tex\latex\amsfonts\amsfonts.sty" +Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 106. +)) +(Z:\scc300\report\final-report.aux) +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 81. +LaTeX Font Info: ... okay on input line 81. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 81. +LaTeX Font Info: ... okay on input line 81. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 81. +LaTeX Font Info: ... okay on input line 81. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 81. +LaTeX Font Info: ... okay on input line 81. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 81. +LaTeX Font Info: ... okay on input line 81. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 81. +LaTeX Font Info: ... okay on input line 81. + +-- Lines per column: 50 (approximate, difference = 8.53687pt). +("C:\Program Files (x86)\MiKTeX\tex\context\base\supp-pdf.mkii" +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count162 +\scratchdimen=\dimen198 +\scratchbox=\box66 +\nofMPsegments=\count163 +\nofMParguments=\count164 +\everyMPshowfont=\toks39 +\MPscratchCnt=\count165 +\MPscratchDim=\dimen199 +\MPnumerator=\count166 +\makeMPintoPDFobject=\count167 +\everyMPtoPDFconversion=\toks40 +) +*geometry* driver: auto-detecting +*geometry* detected driver: pdftex +*geometry* verbose mode - [ preamble ] result: +* driver: pdftex +* paper: a4paper +* layout: +* layoutoffset:(h,v)=(0.0pt,0.0pt) +* modes: +* h-part:(L,W,R)=(56.9055pt, 483.69687pt, 56.9055pt) +* v-part:(T,H,B)=(56.9055pt, 731.23584pt, 56.9055pt) +* \paperwidth=597.50787pt +* \paperheight=845.04684pt +* \textwidth=483.69687pt +* \textheight=731.23584pt +* \oddsidemargin=-15.36449pt +* \evensidemargin=-15.36449pt +* \topmargin=-35.81992pt +* \headheight=12.0pt +* \headsep=8.45543pt +* \topskip=14.45398pt +* \footskip=23.45547pt +* \marginparwidth=20.0pt +* \marginparsep=10.0pt +* \columnsep=12.045pt +* \skip\footins=13.00848pt plus 5.7815pt minus 2.89075pt +* \hoffset=0.0pt +* \voffset=0.0pt +* \mag=1000 +* \@twocolumntrue +* \@twosidefalse +* \@mparswitchfalse +* \@reversemarginfalse +* (1in=72.27pt=25.4mm, 1cm=28.453pt) + +\c@lstlisting=\count168 +ABD: EveryShipout initializing macros +LaTeX Font Info: Try loading font information for OT1+phv on input line 87. + +("C:\Program Files (x86)\MiKTeX\tex\latex\psnfss\ot1phv.fd" +File: ot1phv.fd 2001/06/04 scalable font definitions for OT1/phv. +) +LaTeX Font Info: Calculating math sizes for size <14.05249> on input line 87 +. +LaTeX Font Info: Try loading font information for U+msa on input line 87. + +("C:\Program Files (x86)\MiKTeX\tex\latex\amsfonts\umsa.fd" +File: umsa.fd 2013/01/14 v3.01 AMS symbols A +) +LaTeX Font Info: Try loading font information for U+msb on input line 87. + +("C:\Program Files (x86)\MiKTeX\tex\latex\amsfonts\umsb.fd" +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) +LaTeX Font Info: Try loading font information for U+pzd on input line 87. + +("C:\Program Files (x86)\MiKTeX\tex\latex\psnfss\upzd.fd" +File: upzd.fd 2001/06/04 font definitions for U/pzd. +) [1{C:/Users/Rumps/AppData/Local/MiKTeX/2.9/pdftex/config/pdftex.map} + + + +] +LaTeX Font Info: Font shape `OT1/phv/bx/n' in size <14.05249> not available +(Font) Font shape `OT1/phv/b/n' tried instead on input line 91. +LaTeX Font Info: Font shape `OT1/phv/bx/sc' in size <14.05249> not available + +(Font) Font shape `OT1/phv/b/sc' tried instead on input line 91. +LaTeX Font Info: Try loading font information for OT1+pcr on input line 95. + +("C:\Program Files (x86)\MiKTeX\tex\latex\psnfss\ot1pcr.fd" +File: ot1pcr.fd 2001/06/04 font definitions for OT1/pcr. +) +Underfull \hbox (badness 10000) in paragraph at lines 93--98 +\OT1/ppl/m/n/12.045 All work-ing doc-u-ments and re-sults can be found at + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 93--98 + + [] + +[2 + +] +LaTeX Font Info: Font shape `OT1/phv/bx/n' in size <9.03374> not available +(Font) Font shape `OT1/phv/b/n' tried instead on input line 102. + [3] +LaTeX Font Info: Calculating math sizes for size <12.045> on input line 140. + + [4] [5] [6] +LaTeX Font Info: Font shape `OT1/phv/bx/n' in size <12.045> not available +(Font) Font shape `OT1/phv/b/n' tried instead on input line 169. + +Underfull \hbox (badness 10000) in paragraph at lines 171--172 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 173--174 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 175--176 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 177--178 + + [] + +[7] +LaTeX Font Info: Try loading font information for OMS+ppl on input line 191. + + ("C:\Program Files (x86)\MiKTeX\tex\latex\psnfss\omsppl.fd" +File: omsppl.fd +) +LaTeX Font Info: Font shape `OMS/ppl/m/n' in size <9.03374> not available +(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 191. + [8] [9] +LaTeX Font Info: Font shape `OMS/ppl/m/n' in size <12.045> not available +(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 206. + +Underfull \hbox (badness 10000) in paragraph at lines 210--213 + + [] + + +Overfull \hbox (16.83781pt too wide) in paragraph at lines 216--216 + [][][][]\OT1/ppl/m/n/12.045 EmerGen(e)tic + [] + +LaTeX Font Info: Font shape `OT1/phv/m/it' in size <12.045> not available +(Font) Font shape `OT1/phv/m/sl' tried instead on input line 230. + +Underfull \hbox (badness 10000) in paragraph at lines 232--233 + + [] + +[10] [11] ("C:\Program Files (x86)\MiKTeX\tex\latex\listings\lstlang1.sty" +File: lstlang1.sty 2014/09/06 1.5e listings language file +) +Underfull \hbox (badness 10000) in paragraph at lines 285--287 + + [] + +[12] +Underfull \hbox (badness 10000) in paragraph at lines 288--289 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 297--298 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 299--300 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 309--311 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 312--313 + + [] + +[13] +LaTeX Font Info: Font shape `OT1/phv/bx/n' in size <10.03749> not available +(Font) Font shape `OT1/phv/b/n' tried instead on input line 334. +LaTeX Font Info: Font shape `OT1/pcr/bx/n' in size <10.03749> not available +(Font) Font shape `OT1/pcr/b/n' tried instead on input line 334. +LaTeX Font Info: Font shape `OT1/phv/m/it' in size <10.03749> not available +(Font) Font shape `OT1/phv/m/sl' tried instead on input line 338. +LaTeX Font Info: Font shape `OT1/pcr/m/it' in size <10.03749> not available +(Font) Font shape `OT1/pcr/m/sl' tried instead on input line 338. + [14] +LaTeX Font Info: Font shape `OT1/phv/bx/sc' in size <10.03749> not available + +(Font) Font shape `OT1/phv/b/sc' tried instead on input line 357. +LaTeX Font Info: Font shape `OT1/pcr/bx/sc' in size <10.03749> not available + +(Font) Font shape `OT1/pcr/b/sc' tried instead on input line 357. + [15] +Underfull \hbox (badness 10000) in paragraph at lines 420--421 +\OT1/ppl/m/n/12.045 Within the [][][][] method,[] the [][][] com-po-nent within + + [] + +[16] ("C:\Program Files (x86)\MiKTeX\tex\latex\listings\lstlang1.sty" +File: lstlang1.sty 2014/09/06 1.5e listings language file +) +Underfull \hbox (badness 2435) in paragraph at lines 445--446 +\OT1/ppl/m/n/12.045 If the python script is called with a gen-er-a-tion ar-gu-m +ent of `0' it calls the + [] + +[17] ("C:\Program Files (x86)\MiKTeX\tex\latex\listings\lstlang1.sty" +File: lstlang1.sty 2014/09/06 1.5e listings language file +) +("C:\Program Files (x86)\MiKTeX\tex\latex\listings\lstlang1.sty" +File: lstlang1.sty 2014/09/06 1.5e listings language file +) [18] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [19] +[20] (Z:\scc300\dat\helloworld\output50.txt) +(Z:\scc300\dat\helloworld\output50.txt) (Z:\scc300\dat\helloworld\output0.txt +[21]) (Z:\scc300\dat\helloworld\output0.txt) +(Z:\scc300\dat\helloworld\output100.txt) +(Z:\scc300\dat\helloworld\output100.txt) +Underfull \hbox (badness 10000) in paragraph at lines 614--616 + + [] + +<./img/difffile-large.PNG, id=91, 455.45157pt x 255.95625pt> +File: ./img/difffile-large.PNG Graphic file (type png) + + +Package pdftex.def Info: ./img/difffile-large.PNG used on input line 623. +(pdftex.def) Requested size: 212.82779pt x 119.60815pt. + +<./img/difffile-large-wo.PNG, id=92, 455.45157pt x 255.95625pt> +File: ./img/difffile-large-wo.PNG Graphic file (type png) + + +Package pdftex.def Info: ./img/difffile-large-wo.PNG used on input line 627. +(pdftex.def) Requested size: 212.82779pt x 119.60815pt. + +<./img/samefile-images.PNG, id=93, 455.45157pt x 255.95625pt> +File: ./img/samefile-images.PNG Graphic file (type png) + + +Package pdftex.def Info: ./img/samefile-images.PNG used on input line 631. +(pdftex.def) Requested size: 212.82779pt x 119.60815pt. + +<./img/samefile-images-wo.PNG, id=94, 455.45157pt x 255.95625pt> +File: ./img/samefile-images-wo.PNG Graphic file (type png) + + +Package pdftex.def Info: ./img/samefile-images-wo.PNG used on input line 635. +(pdftex.def) Requested size: 212.82779pt x 119.60815pt. + [22] + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 643. + + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 644. + + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 646. + + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 646. + + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 646. + + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 646. + + +Package wrapfig Warning: wrapfigure used inside a conflicting environment on in +put line 647. + + +Underfull \hbox (badness 4254) in paragraph at lines 642--649 +\OT1/ppl/m/n/12.045 Tests were then run on the test suite + [] + +[23 ] [24] +Underfull \hbox (badness 10000) in paragraph at lines 664--665 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 666--667 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 668--669 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 670--671 + + [] + +[25] [26] (Z:\scc300\report\final-report.bbl +LaTeX Font Info: Calculating math sizes for size <9.03374> on input line 100 +. +) [27] +(Z:\scc300\src\emergenetic\emergenetic.dn +Missing character: There is no  in font pcrr7t! +Missing character: There is no © in font pcrr7t! + [28] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [29] +Overfull \hbox (9.06848pt too wide) in paragraph at lines 157--158 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][] + [] + + +Overfull \hbox (181.78821pt too wide) in paragraph at lines 159--160 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][][][][][][][][][][][][][][][][][][][][][][][][][][] + [] + + +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [30]) +[31] (Z:\scc300\src\helloworld\project\helloworld\mutator.py +Overfull \hbox (61.7654pt too wide) in paragraph at lines 47--48 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][] + [] + + +Overfull \hbox (61.7654pt too wide) in paragraph at lines 52--53 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][] + [] + +[32]) [33] (Z:\scc300\src\cachingpolicy\cachebackup\CacheHandlerBase.dn +Missing character: There is no  in font pcrr7t! +Missing character: There is no © in font pcrr7t! + +[34] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [35] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [36] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [37]) +[38] (Z:\scc300\src\cachingpolicy\project\cachingpolicy\mutator.py [39] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [40] +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [41] +Overfull \hbox (37.67543pt too wide) in paragraph at lines 218--219 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][] + [] + + +Overfull \hbox (31.65294pt too wide) in paragraph at lines 225--226 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][][] + [] + + +Overfull \hbox (67.78789pt too wide) in paragraph at lines 226--227 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][][][][][][][] + [] + + +Overfull \hbox (51.22592pt too wide) in paragraph at lines 227--228 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][] + [] + + +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [42] +Overfull \hbox (71.87785pt too wide) in paragraph at lines 233--235 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][][][][][][][][] + [] + + +Underfull \vbox (badness 10000) has occurred while \output is active [] + + [43] +Overfull \hbox (58.75392pt too wide) in paragraph at lines 325--326 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] + [] + +) (Z:\scc300\src\cachingpolicy\emergenetic.dn [44] +Overfull \hbox (466.77783pt too wide) in paragraph at lines 148--149 +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] +[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][ +][][][][][][][] + [] + +) (Z:\scc300\src\cachingpolicy\project\cachingpolicy\setup.sh) +(Z:\scc300\src\cachingpolicy\project\cachingpolicy\config.conf [45]) +(Z:\scc300\dat\cache\difffile-large\17\chromosomes.txt) [46] +(Z:\scc300\dat\runTests.sh) [47] (Z:\scc300\report\final-report.aux) + +LaTeX Font Warning: Size substitutions with differences +(Font) up to 1.98875pt have occurred. + + ) +Here is how much of TeX's memory you used: + 18404 strings out of 493921 + 369080 string characters out of 3146480 + 519461 words of memory out of 3000000 + 21258 multiletter control sequences out of 15000+200000 + 58638 words of font info for 147 fonts, out of 3000000 for 9000 + 844 hyphenation exceptions out of 8191 + 55i,18n,67p,1330b,1578s stack positions out of 5000i,500n,10000p,200000b,50000s +{C:/Program Files (x86)/MiKTeX/fonts/enc/dvips/fontname/8r.enc} +Output written on final-report.pdf (47 pages, 383434 bytes). +PDF statistics: + 242 PDF objects out of 1000 (max. 8388607) + 0 named destinations out of 1000 (max. 500000) + 33 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/report/final-report.pdf b/report/final-report.pdf new file mode 100644 index 0000000..1cdfe5f Binary files /dev/null and b/report/final-report.pdf differ diff --git a/report/final-report.synctex.gz b/report/final-report.synctex.gz new file mode 100644 index 0000000..64c0512 Binary files /dev/null and b/report/final-report.synctex.gz differ diff --git a/report/final-report.tex b/report/final-report.tex new file mode 100644 index 0000000..eb909ad --- /dev/null +++ b/report/final-report.tex @@ -0,0 +1,753 @@ +\documentclass[compsoc,12pt,a4paper]{IEEEtran} +\usepackage{blindtext} +\usepackage{color} +\usepackage[margin=2cm]{geometry} +\usepackage{graphicx} +\usepackage{listings} +\usepackage{tikz} +\usetikzlibrary{shapes,arrows} +\usepackage{wrapfig} + +\definecolor{dkgreen}{rgb}{0,0.6,0} +\definecolor{gray}{rgb}{0.5,0.5,0.5} +\definecolor{mauve}{rgb}{0.58,0,0.82} + +\lstset{ frame=none, + aboveskip=3mm, + belowskip=3mm, + showstringspaces=false, + columns=flexible, + basicstyle={\small\ttfamily}, + numbers=none, + numberstyle=\tiny\color{gray}, + keywordstyle=\color{blue}, + commentstyle=\color{dkgreen}, + stringstyle=\color{mauve}, + breaklines=true, + breakatwhitespace=true, + tabsize=3, + escapeinside={(**}{*)} } + +\usepackage{cite} +\graphicspath{{./img/}} +\DeclareGraphicsExtensions{.PNG} +\usepackage[cmex10]{amsmath} +\interdisplaylinepenalty=2500 +\usepackage{algorithm} +\usepackage{algorithmic} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{wrapfig} + +% Define block styles +\tikzstyle{decision} = [diamond, draw, fill=blue!20, text width=4.5em, text badly centered, node distance=3cm, inner sep=0pt] +\tikzstyle{block} = [rectangle, draw, fill=blue!20, text width=5em, text centered, rounded corners, minimum height=4em] +\tikzstyle{line} = [draw, -latex'] +\tikzstyle{cloud} = [draw, ellipse,fill=red!20, node distance=3cm, minimum height=2em] + +% *** SUBFIGURE PACKAGES *** +%\usepackage[tight,footnotesize]{subfigure} +% subfigure.sty was written by Steven Douglas Cochran. This package makes it +% easy to put subfigures in your figures. e.g., "Figure 1a and 1b". For IEEE +% work, it is a good idea to load it with the tight package option to reduce +% the amount of white space around the subfigures. subfigure.sty is already +% installed on most LaTeX systems. The latest version and documentation can +% be obtained at: +% http://www.ctan.org/tex-archive/obsolete/macros/latex/contrib/subfigure/ +% subfigure.sty has been superceeded by subfig.sty. + + +%\usepackage[caption=false]{caption} +%\usepackage[font=footnotesize]{subfig} +% subfig.sty, also written by Steven Douglas Cochran, is the modern +% replacement for subfigure.sty. However, subfig.sty requires and +% automatically loads Axel Sommerfeldt's caption.sty which will override +% IEEEtran.cls handling of captions and this will result in nonIEEE style +% figure/table captions. To prevent this problem, be sure and preload +% caption.sty with its "caption=false" package option. This is will preserve +% IEEEtran.cls handing of captions. Version 1.3 (2005/06/28) and later +% (recommended due to many improvements over 1.2) of subfig.sty supports +% the caption=false option directly: +%\usepackage[caption=false,font=footnotesize]{subfig} +% +% The latest version and documentation can be obtained at: +% http://www.ctan.org/tex-archive/macros/latex/contrib/subfig/ +% The latest version and documentation of caption.sty can be obtained at: +% http://www.ctan.org/tex-archive/macros/latex/contrib/caption/ + + +\hyphenation{op-tical net-works semi-conduc-tor} + +\begin{document} + + \title{\vspace{8.0cm}---EmerGen(e)tic---\\Exploring the use\\of genetic algorithms\\in emergent distributed\\systems} + + \author{\vspace{2.0cm}Ben Goldsworthy, 33576556\\Computer Science BSc} + + \maketitle + + \onecolumn + + \section*{Declaration} + + I certify that the material contained in this dissertation is my own work and does not contain unreferenced or unacknowledged material. I also warrant that the above statement applies to the implementation of the project and all associated documentation. Regarding the electronically submitted version of this submitted work, I consent to this being stored electronically and copied for assessment purposes, including the School's use of plagiarism detection systems in order to check the integrity of assessed work.\\ + I agree to my dissertation being placed in the public domain, with my name explicitly included as the author of the work.\\ + All working documents and results can be found at \lstinline|www.lancaster.ac.uk/ug/goldswor/scc300/|.\\\\ + Date:\\ + Signed: + + + \newpage + + \begin{abstract} + Adaptive and emergent systems exist to attempt to answer the deficiencies inherent to distributed systems, and the necessarily finite ability of any programmer to predict all possible eventualities in which his software may one day find itself. This paper argues that these systems fail to go far enough, and then proposes a further development---genetic systems---which utilises genetic programming to extend the versatility of a given system massively, if not infinitely. This paper then proceeds to detail the EmerGen(e)tic framework for rapidly testing genetic algorithm modules within emergent systems, as well as an example module pertaining to the cache updating behaviour of a web server. This paper concludes by proposing further avenues of potentially-fruitful research based upon these programs and its findings. + \end{abstract} + + \newpage + + \section{Introduction} + \label{sec:introduction} + + Coulouris \textit{et al.} (2012) define a \textit{distributed system} as `[...]one in which components located at networked computers communicate and coordinate their actions only by passing messages.'\cite{distsys} By the very nature of distributed computing, any system will---as a whole---experience a range of fluctuating conditions and environments that may affect its performance. Although a well-designed, reliable distributed system will be developed to be `as fault tolerant as possible'\cite{reliable} and with as many of these potential operating environments as possible in mind, the totality of all possible conditions for all possible futures in which the system remains in use is impossible for the original developer(s) to have been entirely predicted and accounted for. This inhibits the universality of current distributed systems, as well as incurring future maintenance and development costs when they need to be adapted for future circumstances.\\ + \textit{Adaptive systems} are a subset of distributed systems in which the system is given a number of submodules that define different behaviour, and the system is programmed with policies for determining which submodule to use for a given task. An example may be a file server that has a compression module activate when serving a file over a given filesize. Whilst this adaptive behaviour does increase the system's operational range, it still requires manual programming of policies and thus suffers from the same issues as the general distributed systems.\\ + \textit{Emergent systems} are a proposed solution to these limitations. Emergent systems are a subset of adaptive systems in which the system itself determines the best configuration to deal with a given situation by trying multiple configurations and assessing their performance against a given metric. This, coupled with some form of storage for recording previously-discovered optimum solutions that can be consulted heuristically for improved performance, provides a more adaptive final system whilst simultaneously reducing development overheads.\\ + Filho \& Porter (2016) best outline the problem in response to which emergent systems have been developed, stating that (emphasis theirs) `[human-centric] approaches [to self-organising software] rely on prediction of how a system will respond to environments (which may turn out to be false) and result in \textit{inflexibility} [whilst a] \textit{machine-centric} approach [...] moves the burden of complexity into software itself, avoids the need for prediction of behaviours, and supports total flexibility [...]'.\cite{machinecentric}\\ + However, these emergent systems are not too without their limitations. Whilst they do possess far more flexibility with regards to arranging themselves into new and unpredicted configurations than does a simpler adaptive system, they are yet constrained by the finite pool of components they have access to, which are still developed by human hand.\\ + \begin{algorithm} + \caption{Basic genetic algorithm} + \label{alg1} + \begin{algorithmic} + \REQUIRE initial population + \REQUIRE num. of generations + \REQUIRE num. of candidates per generation + \FORALL{generations} + \FORALL{chromosomes in generation} + \STATE{run test on chromosome} + \RETURN{fitness score of chromosome} + \ENDFOR + \FOR{strongest chromosome(s) in generation} + \STATE{copy over to next generation} + \ENDFOR + \FOR{remaining chromosomes in generation} + \IF{small probability = true} + \STATE{apply mutation/crossover operation} + \ENDIF + \STATE{copy over to next generation} + \ENDFOR + \ENDFOR + \end{algorithmic} + \end{algorithm} + \textit{Genetic algorithms} rely on metaphors from evolutionary biology such as random mutation and natural selection in order to develop---over the course of multiple iterations and utilising a finite set of operations---improved software, with each generation ideally moving closer towards an optimal solution as specified via the result of a given fitness function $f\left(\right)$. They have been used to produce everything from spaceship antennae\cite{antenna} to software bug checkers.\cite{genprog} In a previous work,\cite{ants} this author applied genetic algorithms to the development of simulated ants. Algorithm \ref{alg1} shows the algorithm by which genetic programming is performed.\\ + On the one hand, we have systems that need to be freed from human development as much as possible in order to be generalisable to the widest range of possible operating environments. On the other, we have a programming approach in which the human developer sets up a number of variables before reclining whilst the computer handles the rest of the time-consuming programming work---the two fields would appear to be ready allies. If genetic programming could be effectively applied to the generation of components for an emergent software system, it would allow the creation of an infinite pool of potential components and allow the system to theoretically surmount any given situation, given enough time.\\ + Thus, the research questions that this project aims to satisfy are: + \begin{itemize} + \item can genetic algorithms be productively used to produce optimum components for an emergent system? and + \item assuming so, what are the optimal conditions for doing so (i.e. mutation probabilities, generation sizes, etc.)? + \end{itemize} + From these research questions come the aims for this project; they are: + \begin{itemize} + \item to produce a framework for enabling rapid development of genetic improvement tests, + \item to test a small, simple program to hopefully demonstrate improvement through application of these techniques and + \item to repeat the tests multiple times with a variety of conditions and see what, if any, trends emerge. + \end{itemize} + This report is divided into eight sections: + \begin{enumerate} + \item `Introduction', in which the broad goal of the project in question is outlined, + \item `Background', in which the history of the field in question is outlined in more detail, + \item `Design', in which the design of the present solution is outlined in a non-technical manner, from first principles, + \item two `Implementation' sections, in which the technical implementation of both the EmerGen(e)tic genetic testing framework and the specific \lstinline|cachingpolicy| module is detailed, + \item `The System in Operation', in which usage---and normal output---of the systems above are described, + \item `Testing \& Evaluation', in which the results of testing on the systems above are investigated and the project as a whole evaluated, with its successes and failures candidly discussed and + \item `Conclusion', in which the research questions above are revisited and avenues for future research signposted. + \end{enumerate} + + \newpage + + \section{Background} + \label{sec:background} + + \subsection{Assumptions} + + This project operates on a foundation of two assumptions, neither of which---though they may both appear to be---are axiomatic.\\ + + \noindent \textbf{Assumption \#1: Programming is hard}\\ + + \noindent IBM found that the cost of fixing a bug can range from a base cost (for one discovered during the requirements elicitation phase of software design) to 100$\times$ that (for one identified in the maintenance phase).\cite{bugcost} With the lengths of written software steadily increasing---1993's Windows NT 3.1 had 4.5m lines of code to 2003's Windows Server 2003's 50m---and an average of `about 15--50 errors per 1000 lines of delivered code',\cite{1000} these problems are being exacerbated.\footnote{For further exploration by myself of the resultant security risks of this, amongst other factors, see \cite{cni}.} As such we desire to systems that will perform as many programming responsibilities on our behalf as possible, as well as as much of the checking, testing and validation work as we can get away with---repetitive, methodical tasks such as testing especially represent the perfect area for a computer, but not man. We also desire systems that can be constructed out of smaller, simpler parts that can be more rigorously tested prior to deployment.\footnote{cf. the `Unix philosophy', best detailed in \cite{unix}} It is these goals that has led to the development of distributed, adaptive and emergent systems, as well as genetic programming.\\ + + \noindent \textbf{Assumption \#2: Circumstances change}\\ + + \noindent It would be hubris \textit{par excellence} to assume that humanity has learnt all that there is to learn and can be surprised no longer. Bronze age man discovered ironwork, assumptions of classical physics were rent asunder by the discovery of quantum physics and the discovery of non-Euclidean geometry is said to have `marked the end of an entire line of human thought, one that had dominated intellectual efforts in the West for centuries.'\cite{geometry} No one programmer---nor a team of programmers---can hope to have perfect, 20/20 foresight encompassing all of the environmental possibilities in which their system may find itself deployed in the future. Even if they could, theoretically, handle all possible situations as are known to them now, there is every possibility of a non-Euclidean geometry-esque upending of the conventional wisdom occurring at an unspecified point in the future, entirely incomprehensible from within the bounds of their Euclidean worldview---they would be akin to the denizens of Abbott's \textit{Flatland}, trying to conceive of the third dimension. + + \subsection{Distributed and Adaptive Systems} + + \textit{Distributed systems}---amusingly described by Lamport (1987) as `[a system] in which the failure of a computer you didn't even know existed can render your own computer unusable'\cite{email}---have their origins in the early days of computing and the concept of multiprogramming. Carr, Crocker \& Cerf (1970) outlined ARPANET, `one of the most ambitious computer networks attempted to date'.\cite{rfc} As one of the first networks, ARPANET serves an example of one of the first instances of distributed computing and a predecessor to the modern-day Internet. Coulouris \textit{et al.}'s definition of a distributed system as `[...]one in which components located at networked computers communicate and coordinate their actions only by passing messages'\cite{distsys} may, however, begin to make the drawbacks of such a system apparent. As these computers are in different geographic locations, their needs and experiences may differ---a program written in California may work fine on the fast, reliable internet connections that are all its developer may have ever experienced, but less so for the instance of it running in rural India.\\ + One solution to these issues is \textit{adaptive systems}, in which a distributed system is given a number of submodules containing different approaches to its tasks. The developer will then program in various policies for which modules to use in which conditions. Examples of this could include a live online video player that resorts to a different quality of transmission when being broadcast to a client with a suboptimal network connection. Again, the Internet is an excellent example of an adaptive system: with various protocols on offer, a developer can choose the one that best suits a given need. If error detection and correction is important, TCP is the tool for the job; if it is not, then UDP provides a faster transmission with less overhead.\\ + However, these adaptive systems fail to resolve the initial issue of the developer having to predict the myriad situations his program may find itself running in in the future. By still requiring the developer's input in specifying the various module combination strategies and policies, all these systems achieve is to allow the developer to write more generalised, less specific (sub)programs. This may be beneficial for rapid reuse elsewhere, but is otherwise not the solution we seek. + + \subsection{Emergent Systems} + + One such proposed solution, however, is the \textit{emergent system}, or an adaptive system in which the program itself (or a framework on top of it) designs its own policies based on trial-and-error and recording performance rates of different combinations of submodules, the name coming from the possibility of such a system discovering optimal behaviour unpredicted by its human creators.\\ + Dana\footnote{Dana documentation and downloads can be found at \lstinline|www.projectdana.com|} is a component-based language designed specifically for emergent system programming by Porter (2014), described by the author as `an imperative, procedural, interpreted language, [that] is multi-threaded, and features only interface, record and primitive types'\cite{dana}---it is also `syntactically similar to contemporary languages like Java'\cite{dana}.\\ + Filho \& Porter (2016a) describe a web server written in Dana.\footnote{For an explanation of the function of Filho \& Porter's web server, as well as concepts such as `caching' and `compression', see \S \ref{sec:design}} The web server receives requests for files---a mixture of file types and sizes---from clients and serves them up. The server can construct behaviour out of a number of components that enable different policies for cache updating, file compression, etc. The authors test the server in every possible configuration and against different styles of workload, measuring the request response time per configuration.\\ + The authors showed that different configurations gave markedly different results---for example, for a `Workload 1 [consisting] of one client repeatedly requesting only one text-only HTML file, [a particular architecture] performs best because, in this configuration, the web servers always compress the requested files, and once the file is returned to the load balancer, it is stored in a small content cache at the load balancer.'\cite{machinecentric} Meanwhile, a cacheless architecture performed better at a workload consisting of `one client requesting a different text-only HTML file for every request'\cite{machinecentric} as caching would provide no benefit for a constantly-changing series of requests and would only add pointless overhead.\\ + In a further paper, Filho \& Porter (2016b), the authors go onto elucidate the limitations of a simple adaptive system, arguing that `[the] requirement [for human specification of control strategies] is fundamentally opposed to the core ideas behind autonomic computing, which are borne of the increasing difficulty for humans to understand modern software systems in dynamic environments.'\cite{losingcontrol} Developing further their web server platform, they implement a perception and learning system so that the web server can analyse the performance of varied configurations and determine an optimum arrangement for a given task. Finally, in Filho \textit{et al.} (2016), this is consolidated into the single framework RE$^{\text{X}}$, which `produce[s] systems that are responsive to the actual conditions that they encounter at runtime, and the way they perceive their behaviour in these conditions.'\cite{rex}\\ + Other frameworks within the same field of emergent systems exist, such as Elkhodary, Esfahani \& Malek (2010)'s FUSION,\cite{fusion} but I assert the following with this paper: that the very idea of emergent systems as a whole fails to go far enough towards solving the issues it was formulated in response to. + + \subsection{`Genetic Systems'} + + Floyd (1979) said that the following words were written on the wall of a Stanford University graduate student office: `I would rather write programs to help me write programs than write programs.'\cite{floyd} This is a succinct description of the goals of genetic programming, in which representations (usually tree representations) of computer programs are modified using a set of mutation and crossover operators and a set of varying probabilities for each to occur. These changes take place across multiple generations and should, hopefully, trend towards better-performing programs. The applications are vast: Le Goues \textit{et al.} (2012) applied them to automated software bug fixers;\cite{genprog} Hansen \textit{et al.} (2007) to counter-cyberterrorism;\cite{security} Hornby \textit{et al.} (2015) to the shape of spacecraft antennae;\cite{antenna} and the author of this paper to the production of simulated ants.\cite{ants}\\ + Indeed, the wall of Stanford's student office neatly encapsulates the thinking behind the proposal of this paper as to the viability and desirability of applying genetic programming techniques within the emergent system space--what this author will propose to be described as `genetic systems'. If an emergent system can already assemble configurations of provided submodules, test them and rank them, and the goal is to eliminate the developer from the software development equation as much as possible, then what is next? Why not have the system assemble the submodules themselves? This would increase the pool of potential submodules available to the program to be theoretically infinite, and the same benefits of this emergent behaviour would apply here too. It is this hypothesis that is to be tested within this paper. + + \newpage + + \section{Design} + \label{sec:design} + + Within this section the design of the EmerGen(e)tic (from `emergent' and `genetic') system is outlined. Following that, the web server and caching system used within the \lstinline|cachingpolicy| module are outlined, from first principles, for the non-technical user's understanding. For a technical overview, see \S \ref{sec:cachingpolicyimpl}. + + \subsection{EmerGen(e)tic} + + The primary goal of this project was to produce a framework for quickly and easily allowing future projects to test the effects of genetic algorithms on varying elements of varying systems. To do this, a master Dana program was created which runs through each generation, calling a separate file (hereafter referred to as a \textit{module}) to handle all of the the evolutionary logic---the mutations, crossovers, selections, etc. This is so that future developers can easily plug `n' play with their own genetic modification modules in the future. The master program will then run through all the candidates from each generation to test their responses to differing stimuli. The testing functionality is contained within a single method, and so should be the only part of the EmerGen(e)tic code that a future developer needs to modify to implement their own project.\\ + To assist with generalisability, as many settings as possible (e.g. mutation probability, file(s) to test with, number of generations) were left to be externally set via either command-line arguments or config. files.\\ + The below flowchart shows the intended operation of the system:\\ + \begin{center} + \begin{tikzpicture}[node distance = 4.5cm, auto] + % Place nodes + \node [block] (init) {EmerGen(e)tic}; + \node [block, left of=init] (results) {Results}; + \node [block, below of=results] (script) {Mutation module}; + \node [block, below of=script] (generation) {Generation $x$}; + % Draw edges + \path [line] (init) -- (script) node[midway,left,align=center] {1. For each gen.\\call module}; + \path [line] (script) -- (generation) node[midway,left,align=center] {2. Create next\\gen.'s pop.}; + \path [line] (init) |- (generation) node[midway,right,align=center] {3. Test generation}; + \path [line] (init) -- (results) node[midway,above,align=center] {4. Output\\results}; + \end{tikzpicture} + \end{center} + + \subsection{The Web Server} + + \subsubsection{How a web server works} + + A \textit{web server} is a type of computer. It can receive requests from other computers (called `clients') for the files that are located within it via a number of methods, usually across an Internet connection, such as HTTP. Once it has received a request, which will contain the name of the file requested, it searches its file storage for a match. If it finds it, it sends the data of the file back to the client. If it does not, it should return a message that the client knows to interpret as an error message. Below is a flowchart of how a web server works:\\ + \begin{center} + \begin{tikzpicture}[node distance = 6cm, auto] + % Place nodes + \node [block] (client) {Client}; + \node [block, below of=client] (webserver) {Web Server}; + \node [block, right of=webserver] (file) {File Store}; + % Draw edges + \path [line] (client) -- (webserver) node[midway,left,align=center] {1. Client requests\\file}; + \path [line] (webserver) -- (file) node[midway,above,align=center] {2. Server retrieves\\file from\\file store}; + \path [line] (file) -- (webserver); + \path [line] (webserver) -- (client) node[midway,right,align=center] {3. Server returns\\file\\(or error)}; + \end{tikzpicture} + \end{center} + + \subsubsection{Added extras} + + This is the most basic form of web server---for every request, it trawls through its files for a match and then returns that to the client. However, there are numerous extra functions that can be added to improve performance, and which can be combined to best suit various situations. For example, files can be compressed through various schemes in order to reduce their filesize before sending, and then decompressed at the client's end, which shortens the amount of time taken to transmit the (now-smaller) file.\\ + However, the one most relevant to this project is \textit{caching}. In caching, a cache is kept---this is a section of storage that is faster to retrieve data from than the regular file store, but which does not have the size to hold the full file store. When a file is returned for a client's request, it is also added to the cache. This means that if a client then requests the same file again, it will be found within the cache and returned faster than if the entire file store had to be searched.\\ + Obviously, the cache will at some point fill up. At this point, various policies for updating a full cache can be implemented. The simplest is to simply start again at the beginning and overwrite the first item. More complex ones can bring in variables like which file was requested least recently, or has been requested the fewest times, in order to try and improve speed. Again, different policies suit different situations, and there is no `magic bullet'. + + \subsubsection{A tale of two web servers} + + The present project is based off of Filho \& Porter's Dana web server code. Their project includes a client program, which is given a list of files grouped by various criteria (e.g. all large files, all image files, mixtures of both, etc.). It then sends the server program HTTP requests for each file in the list until it reaches the end. In this particular version of the software Filho \& Porter's PAL system is implemented, meaning every possible configuration found is tried---this means that each file is tested with every combination of the provided caching and compression methods, and the response time of the server (in ms) recorded. This response time is the metric by which the PAL system ranks various configurations.\\ + The goal of Filho \& Porter's project was to demonstrate improvements in file handling when using different combinations of policies for different types of request patterns. However, for the present project, the system is too complex to control all of the independent variable required for the tests to be run. As such, the scope of inquiry had to be limited to caching policy only. As such, much of Filho \textit{et al.}'s server project code was removed. This left only the caching functionality and some remnants of the web server code. + + \subsection{Caching} + \label{sec:caching} + + Cache behaviour is located within the \lstinline|/cache/CacheHandler*.dn| family of components. Filho \& Porter's server code contains six \lstinline|CacheHandler*| variants, each with different policies for determining which item in a full cache---represented by a fixed-size array---to replace with a newly-requested file, as well as a simple cache system in which the cache is only one item long. The other methods are: + \begin{itemize} + \item serial replacement, where each item in turn is replaced, returning to the first item upon reaching the end of the array, + \item most- and least-frequently used, + \item most- and least-recently used. + \end{itemize} + For example, \lstinline|CacheHandlerMFU.dn| contains the policy for replacing the most-frequently used cache item.\\ + Within each of these variant cache handling policy files there is necessarily a lot of duplicated code. Common to all variants are the method signatures (but not bodies) for: + \begin{itemize} + \item \lstinline|updateCache()|, which updates a full cache using the variant's specified policy, + \item \lstinline|clearCache()|, which clears the cache completely, and + \item \lstinline|getCachedResponse()|, which returns either the item that was received from the cache or \lstinline|null| to the caller. + \end{itemize} + Cache initialisation is handled as a conditional within \lstinline|updateCache()| (i.e. if there is no cache present, it creates one and places the current item in cache index 0).\\ + There are also a series of functions that are only present in individual \lstinline|CacheHandler| files, such as \lstinline|mostRecentlyUsed()| in \lstinline|CacheHandlerMRU.dn|. This does what is says on the tin, returning the most recently-used item from the cache to be overwritten. Another example is \lstinline|random()| (within \lstinline|CacheHandlerR.dn|), which unsurprisingly returns a random item from the cache.\\ + For the genetic algorithm to work it needs a base file. The base file requires all of the common functionality present and marked as out-of-bounds for the genetic algorithm. Included in these out-of-bounds methods would be the full complement of methods such as \lstinline|mostRecentlyUsed()|, which could be called upon or not as decided by a given output program. + + \subsection{The `Cache Policy' Genetic Algorithm} + + The basic workings of a genetic algorithm were covered in \S \ref{sec:introduction}, but here the specifics of the algorithm as applied to this project shall be outlined.\\ + As this project is concerned only with modifying cache updating behaviour, and thus in how to produce an index value given differing formulae, the most important line is line 110 of \lstinline|CacheHandlerBase.dn|: + \begin{lstlisting}[language=Java] + index = 0 + \end{lstlisting} + The formula on the right-hand side of that assignment is the scope for mutation. From that initial `\lstinline|0|' must sprout new formulae---these formulae are what is referred to in the remainder of this report as \textit{chromosomes}. A single \textit{generation} will consist of multiple \lstinline|CacheHandler*.dn| files (or \textit{candidates}), each of which will contain a single chromosome. Within each generation, therefore, shall exist multiple distinct chromosomes. Each of these sets of chromosomes is known as the generation's \textit{population}.\\ + As mentioned before, the basic tools of a genetic algorithm are the operations of \textit{mutation} and \textit{crossover}, which shall be discussed below (along with a heuristic known as `elite selection'):\\ + + \noindent\textbf{Mutation}\\ + + \noindent In mutation, a section of chromosome $A$ is replaced with a new value. For example, from the example chromosome `\lstinline|0|', an operand mutation operation could change it to `\lstinline|4|'. For the mutation within the scope of this project, four types of mutation were implemented: + \begin{itemize} + \item binary operator mutation (e.g. `\lstinline|2+4|' into `\lstinline|2*4|'), + \item operand mutation, + \item unary operator mutation (e.g. `\lstinline|nthMostRecentlyUsed(2)|' into `\lstinline|nthMostFrequently- Used(2)|'), and + \item subtree creation (e.g. `\lstinline|2+2|' into `\lstinline|2+(4*2)|'). + \end{itemize} + The first three simply randomly change elements of the chromosomes in the hopes of finding particularly efficacious variants. The fourth, however, serves the vital role of allowing the chromosomes---which all start as `\lstinline|0|'---to increase in complexity.\\ + + \noindent\textbf{Crossover}\\ + + \noindent In crossover, two chromosomes $A$ and $B$ are selected. A random section of $A$ ($A'$) is then taken and inserted at a random point of $B$ ($B'$) to produce a new chromosome $C$. For example, take + \begin{gather*} + A = \text{ \lstinline|2+(4+3)|}\\ + B = \text{ \lstinline|4*3|} + \end{gather*} + and an $A'$ of `\lstinline|+(4+3)|' and a $B'$ between the `\lstinline|4|' and the `\lstinline|*|'---we produce + \begin{gather*} + C = \text{ \lstinline|4+(4+3)*3|} + \end{gather*} + Variants of crossover also exist, such as multi-point crossover (where multiple $A'$s are copied over to multiple $B'$s). However, for this project, only single-point crossover was implemented due to time constraints.\\ + + \noindent\textbf{Elite Selection}\\ + + \noindent There are a number of time-saving tactics (or \textit{heuristics}) that can be used to speed up the performance of a genetic algorithm. One such heuristic, implemented within this project, is \textit{elite selection}. This takes an arbitrary percentage of top-performing chromosomes for any generation (in this instance, the top 10 \%) and copies them across to the next generation unchanged. This ensures that optimal solutions are not simply discarded upon the next generation. + + \newpage + + \section{Implementation: EmerGen(e)tic} + \label{sec:implementation} + + This section contains a more technically-detailed overview of the implementation of the EmerGen(e)tic program. + + \subsection{Folder Structure} + + The base folder structure for EmerGen(e)tic is as follows: + \begin{itemize} + \item \lstinline|/archives/|, where archives of test run data go when after completion of a script's run, + \item \lstinline|/project/|, which contains the mutation project modules, + \item \lstinline|/resources/|, which contains Dana overhead, + \item \lstinline|/results/|, which contains per-generation and per-script results files and + \item \lstinline|/scripts/|, which contains \lstinline|.script| files for running through multiple tests, grouped by some criterion/criteria. + \end{itemize} + + \subsection{\lstinline|emergenetic.dn|} + + This Dana file contains the framework for running and testing genetic algorithm projects.\footnote{See Appendix \ref{appendix:emergen}} Passed to it are a number of command-line arguments, including the module to load and the number of generations to test. + + \subsubsection{\lstinline|App:main()|} + + The program is entered through the \lstinline|App:main()| method, whereupon the passed arguments are validated---if any are invalid, detailed error messages are output and the program terminates. The method runs the setup file \lstinline|setup.sh| from within the passes module directory (and passes the result to a variable of type \lstinline|RunStatus|, which can be helpful for debugging), and then iterates through each generation. For each generation, it runs the given module's \lstinline|mutator.py| program, followed by the \lstinline|runGeneration()| method.\\ + Upon successfully finishing the iteration of each generation, the program exits with a code of `0'---in the event of invalid arguments, it exits with a code of `1'. + + \subsubsection{\lstinline|runGeneration()|} + + The \lstinline|runGeneration()| calls the \lstinline|runCandidate()| method for each candidate within the given generation. Once this is done, it appends a newline to the \lstinline|results.csv| file within the \lstinline|results| directory. + + \subsubsection{\lstinline|runCandidate()|} + + This is the point at which a future developer will implement their own code for running and testing candidates for their own projects. In the base release of \lstinline|emergenetic.dn|, it is left blank. + + \subsubsection{\lstinline|printResults()|} + + This method prints the results of each test run to output. It then also appends the results of the run to the per-generation results file \lstinline|results|$x$\lstinline|.txt|, and to the per-script results file \lstinline|results.csv| within the \lstinline|results| directory. + + \newpage + + \section{Implementation: \lstinline|cachingpolicy|} + \label{sec:cachingpolicyimpl} + + In this section, the technical implementation of the \lstinline|cachingpolicy| module used for this project is detailed. + + \subsection{Folder Structure} + + In addition to the base folder structure of EmerGen(e)tic, the following directories were added. + \begin{itemize} + \item \lstinline|/cache/|, where the generations of various \lstinline|CacheHandler*.dn| files are kept, each within a directory numbered with their generation number and in files of the format \lstinline|CacheHandler|$x$\lstinline|_|$y$\lstinline|.dn|, where $x$ is the number of the generation and $y$ is the number of the candidate, + \item \lstinline|/cachebackup/|, which contains a fresh copy of \lstinline|CacheHandlerBase.dn| for quickly clearing the \lstinline|/cache/| directory after a full test run, + \item \lstinline|/htdocs/|, which contains all the files to request from the web server, + \item \lstinline|/project/cachingpolicy|, which contains the files for the \lstinline|cachingpolicy| module and + \item \lstinline|/resources/cache|, which contains the Dana specifications for the caching components. + \end{itemize} + + \subsection{Genetic Algorithm search space} + + Before a genetic algorithm can be implemented, the search space must be defined: + \begin{gather*} + \text{Let }c\text{ represent the cache length} \\ + \text{Let }l\text{ represent an AST leaf values} \\ + \text{Let }n\text{ represent an AST node values} \\\\ + l \in \mathbb{N} \\ + n \in \left\{\times, +, -, \div, MostFrequent\left(\right), MostRecent\left(\right), Rand\left(\right) \right\} \\\\ + \text{Let }a\left(n\right)\text{ be a function that returns the arity of function }n \\ + \text{Let }r\text{ represent the result of }n\left(\right)\text{, }n\left(l\right)\text{ or }n\left(l_1, \dots, l_{a\left(n\right)}\right) \\ + \text{Let }i\text{ represent the cache index value to replace} \\\\ + r\in \mathbb{N} \\ + i \in \left\{x \in \mathbb{N} : 0 \leq i \leq c-1\right\} \\ + \therefore i = r \bmod{\left(c-1\right)} + \end{gather*}\\ + In real terms then, the the set of actual Dana operators and methods $n_{Dana}$ used was + \[ n_{Dana} \in \left\{\text{\lstinline|*|}, \text{\lstinline|+|}, \text{\lstinline|-|}, \text{\lstinline|/|}, \text{\lstinline|nthMostFrequentlyUsed()|}, \text{\lstinline|nthMostRecentlyUsed()|}, \text{\lstinline|random()|}\right\} \] + and the resolve flag $res$, which was passed through to \lstinline|nthMostFrequentlyUsed()| and \lstinline|nthMostRecentlyUsed()| as a constant in each individual program, was of the value + \[res \in \left\{\text{\lstinline|n|}, \text{\lstinline|o|}, \text{\lstinline|r|}\right\}\] + + \subsection{\lstinline|CacheHandlerBase.dn|} + + From the various \lstinline|CacheHandler*.dn| files within Filho \& Porter's \lstinline|/cache/| were distilled the common elements of each (the methods covered in \S \ref{sec:caching}), collected into one file.\footnote{See Appendix \ref{appendix:base}} + + \subsubsection{\lstinline|CacheHandler:getGetCachedResponse()|} + + This method returns an item specified in a request from the cache if it exists there---otherwise, it returns \lstinline|null|. + + \subsubsection{\lstinline|CacheHandler:updateCache()|} + + This method updates the cache if a requested item is not already in it. If the cache is full, this method contains the formula for determining the cache index to replace. Lines 70--71---demarcated with the comments \lstinline[language=Java]|// BEGIN| and \lstinline[language=Java]|// END|---indicate to the genetic algorithm its bounds of operation. Within these lines, the method for determining cache index $i$ is determined for each chromosome. + + \subsubsection{\lstinline|CacheHandler:clearCache()|} + + This method clears the cache completely. + + \subsubsection{\lstinline|nthMostFrequentlyUsed()|, \lstinline|nthMostRecentlyUsed()| \& \lstinline|random()|} + + These methods return the item in the cache that fits their criterion (or, in the case of \lstinline|random()|, a random item). Including all of the various most/least frequently/recently used methods would lead to an unnecessarily large file, so they were generalised into the methods \lstinline|nthMostFrequentlyUsed()| and \lstinline|nthMostRecentlyUsed()|, which each take their $n$ as an argument. + + \subsubsection{\lstinline|resolve()|} + + The \lstinline|resolve()| method takes a flag indicating how to resolve the situation of multiple returns from one of the aforementioned three methods (e.g. in the event that the least-frequently used file is not the only file in the cache with that number of hits). The flag can be set to return either the newest item, the oldest or a random choice. + + \subsection{\lstinline|emergenetic.dn|} + + Within the \lstinline|runCandidate()| method,\footnote{See Appendix \ref{appendix:runcand}} the \lstinline|CacheHandler| component within \lstinline|CacheHandler*.dn| is loaded using Dana's \lstinline|RecursiveLoader|, which ensures that all of its dependencies are also loaded. A timer is started and each file within the given script file is requested from the web server. When the script file is finished, the timer is stopped and the overall time taken (and that the value represented ms) is passed to \lstinline|printResults()|. As \lstinline|RecursiveLoader| lacks an \lstinline|unload()| method, each of the loaded components is then looped through and \lstinline|unload()| called on them in turn. + + \subsection{\lstinline|cachingpolicy/mutator.py|} + \label{sec:python} + + This Python file contains the genetic algorithm logic for the \lstinline|cachingpolicy| module.\footnote{See Appendix \ref{appendix:genetic}} It can be run as a standalone Python script or imported as a Python module into other projects. + + \subsubsection{\lstinline|getSubLists()|} + + This method recursively produces a \lstinline|List| of nested \lstinline|List|s representing every subtree present within a given chromosome (i.e. every bracketed expression). + + \subsubsection{\lstinline|crossover()|} + + This method performs single-point crossover between two chromosomes passed to it as arguments $A$ and $B$. It first calls \lstinline|getSubLists()| on $A$ in order to get a \lstinline|List| of all the possible subtrees of $A$. It then randomly chooses points within $B$ until it finds an operand token, at which point it replaces the operand with a randomly-chosen \lstinline|List| from $A$. + + \subsubsection{\lstinline|mutate()|} + + This method performs four distinct multiple-point mutations. If it is the first run it imports the individual mutation probabilities from \lstinline|config.conf|, and if it is the initial population it overrides the mutation probability to be 100 \%. It then recursively iterates over each token in the chromosome and has a chance to possibly apply one of the mutation operations. The recursive element comes in when it encounters a token of type \lstinline|List| (i.e. a bracketed expression), in which case it calls \lstinline|mutate()| upon the sublist. + + \subsubsection{\lstinline|parse()| \& \lstinline|compile()|} + + The former of these methods takes an expression as a string (e.g. `\lstinline|2+(4*2)|') and returns a \lstinline|List| representation (with nested \lstinline|List|s for bracketed expressions). The latter takes such a \lstinline|List| and returns the original string expression. + + \subsubsection{\lstinline|createInitialPop()|} + + If the python script is called with a generation argument of `0' it calls the \lstinline[language=python]|createInitialPop()| method first. This creates an initial population by copying over \lstinline|CacheHanderBase.dn| and applying \lstinline[language=python]|mutate()| to each candidate with a 100 \% mutation probability. + + \subsubsection{\lstinline|readChromosomeFromFile()| \& \lstinline|writeChromosomeToFile()|} + + These methods are simple utility methods for reading and writing chromosomes from and to \lstinline|CacheHandler*.dn| files. + + \subsubsection{\lstinline|hasSubTrees()|} + + This method returns a boolean indicating whether a passed chromosome has nested expressions or not. + + \subsubsection{\lstinline|main()|} + + The \lstinline|main()| method takes the $n$ candidates of previous generation $m$ (passed to it as arguments) and selects the top 10 \% of them to go across unchanged to generation $m+1$. Of the remainder, probabilities of mutation and crossover are applied to each and, when those occur, separate probabilities determine the type of mutation or crossover that will occur. + + \subsection{\lstinline|cachingpolicy/config.conf|} + + \lstinline|mutator.py| reads in its probability values from the file \lstinline|config.conf|.\footnote{For an example \lstinline|config.conf|, see Appendix \ref{appendix:settings}} This file contains a number of name-value pairs. The left hand side of each config. pair is ignored by \lstinline|mutator.py| and is thus present only for the aid of the human user. + + \newpage + + \section{The System in Operation} + + In this section is outlined the process of creating a new module---and running a suit of tests using it---via the EmerGen(e)tic framework. + + \subsection{Creating a Module} + + \subsubsection{Files} + + To create a new module for a future research project, create the folder within the \lstinline|project| directory. Within this directory, create a Python file \lstinline|mutator.py|, which will contain all of your genetic algorithm and a Bashscript file \lstinline|setup.sh| to perform any functions prior to each test such as creating or deleting folders (this may not perform any tasks, but the file must still be present).\footnote{For an example \lstinline|setup.sh|, see Appendix \ref{appendix:setup}} + + \subsubsection{Implementation} + + To implement the new module and test the results of it, code must be written within the \lstinline|runCandidate()| method of the Dana file \lstinline|emergenetic.dn|. Within this method will be defined the process of testing, how to use script files and the metric by which success is measured. The other methods within the file will remain unchanged. + + \subsection{Creating Scripts} + + In order to run a suite of different tests for each candidate, scripts are required. In the \lstinline|cachingpolicy| instance, these script files contain the filenames of different files grouped by some property or properties. For example, \lstinline|difffile-html.script| tests a number of different files, all of which are HTML but are a mixture of sizes, whilst \lstinline|difffile.script| tests different files that are a mixture of HTML and image and have a range of sizes. This can be used to easily showcase the system producing different results that provide optimum behaviour based on different operational conditions. + + \subsection{Running EmerGen(e)tic} + + After compiling the \lstinline|emergenetic.dn| file, the program can be run. It expects four command-line arguments, and can take a fifth optional one. The command is as follows: + \begin{lstlisting}[language=bash] + dana emergenetic