Skip to content

Instantly share code, notes, and snippets.

@manuelleduc
Created November 19, 2015 15:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manuelleduc/c7384d4a754695a02213 to your computer and use it in GitHub Desktop.
Save manuelleduc/c7384d4a754695a02213 to your computer and use it in GitHub Desktop.
using System;
namespace test {
public class DistortedTimeResolver: KResolver {
private static int KEYS_SIZE = 3;
private KChunkSpaceManager _spaceManager;
private KInternalDataManager _manager;
public DistortedTimeResolver(KChunkSpaceManager p_cache, KInternalDataManager p_manager) {
this._spaceManager = p_cache;
this._manager = p_manager;
this._spaceManager.setResolver(this);
}
public KTask lookup(long universe, long time, long uuid, KCallback < KObject > callback) {
DistortedTimeResolver selfPointer = this;
return () => {
try {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (KChunk theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement != null) {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, uuid, (KChunk theObjectUniverseOrderElement) => {
if (theObjectUniverseOrderElement == null) {
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
} else {
long closestUniverse = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) theObjectUniverseOrderElement, time, universe);
selfPointer.getOrLoadAndMark(closestUniverse, KConfig.NULL_LONG, uuid, (KChunk theObjectTimeTreeElement) => {
if (theObjectTimeTreeElement == null) {
selfPointer._spaceManager.unmarkMemoryElement(theObjectUniverseOrderElement);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
} else {
long closestTime = ((KLongTree) theObjectTimeTreeElement).previousOrEqual(time);
if (closestTime == KConfig.NULL_LONG) {
selfPointer._spaceManager.unmarkMemoryElement(theObjectTimeTreeElement);
selfPointer._spaceManager.unmarkMemoryElement(theObjectUniverseOrderElement);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
return;
}
selfPointer.getOrLoadAndMark(closestUniverse, closestTime, uuid, (KChunk theObjectChunk) => {
if (theObjectChunk == null) {
selfPointer._spaceManager.unmarkMemoryElement(theObjectTimeTreeElement);
selfPointer._spaceManager.unmarkMemoryElement(theObjectUniverseOrderElement);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
} else {
KMetaClass resolvedMetaClass = selfPointer._manager.model().metaModel().metaClass(((KObjectChunk) theObjectChunk).metaClassIndex());
KObject newProxy = ((AbstractKModel) selfPointer._manager.model()).createProxy(universe, time, uuid, resolvedMetaClass, closestUniverse, closestTime);
selfPointer._spaceManager.register(newProxy);
callback(newProxy);
}
});
}
});
}
});
}
});
} catch (Exception e) {
//e.printStackTrace();
}
};
}
public KTask lookupAllObjects(long universe, long time, long[] uuids, KCallback < KObject[] > callback) {
DistortedTimeResolver selfPointer = this;
return () => {
try {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (KChunk theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement != null) {
long[] tempObjectUniverseKeys = new long[uuids.Length * 3];
for (int i = 0; i < uuids.Length; i++) {
tempObjectUniverseKeys[i * 3] = KConfig.NULL_LONG;
tempObjectUniverseKeys[i * 3 + 1] = KConfig.NULL_LONG;
tempObjectUniverseKeys[i * 3 + 2] = uuids[i];
}
selfPointer.getOrLoadAndMarkAll(tempObjectUniverseKeys, (KChunk[] objectUniverseOrderElements) => {
if (objectUniverseOrderElements == null || objectUniverseOrderElements.Length == 0) {
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
return;
}
long[] tempObjectTimeTreeKeys = new long[uuids.Length * 3];
for (int i = 0; i < uuids.Length; i++) {
long closestUniverse = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) objectUniverseOrderElements[i], time, universe);
tempObjectTimeTreeKeys[i * 3] = closestUniverse;
tempObjectTimeTreeKeys[i * 3 + 1] = KConfig.NULL_LONG;
tempObjectTimeTreeKeys[i * 3 + 2] = uuids[i];
}
selfPointer.getOrLoadAndMarkAll(tempObjectTimeTreeKeys, (KChunk[] objectTimeTreeElements) => {
if (objectTimeTreeElements == null || objectTimeTreeElements.Length == 0) {
selfPointer._spaceManager.unmarkAllMemoryElements(objectUniverseOrderElements);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
return;
}
long[] tempObjectChunkKeys = new long[uuids.Length * 3];
for (int i = 0; i < uuids.Length; i++) {
long closestTime = ((KLongTree) objectTimeTreeElements[i]).previousOrEqual(time);
if (closestTime != KConfig.NULL_LONG) {
tempObjectChunkKeys[i * 3] = tempObjectTimeTreeKeys[i * 3];
tempObjectChunkKeys[i * 3 + 1] = closestTime;
tempObjectChunkKeys[i * 3 + 2] = uuids[i];
} else {
// TODO System.arraycopy(KContentKey.NULL_KEY, 0, tempObjectChunkKeys, (i * 3), 3);
}
}
selfPointer.getOrLoadAndMarkAll(tempObjectChunkKeys, (KChunk[] theObjectChunks) => {
if (theObjectChunks == null /*|| System.arraycopy == 0*/ ) {
selfPointer._spaceManager.unmarkAllMemoryElements(objectTimeTreeElements);
selfPointer._spaceManager.unmarkAllMemoryElements(objectUniverseOrderElements);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
} else {
KObject[] finalResult = new KObject[uuids.Length];
for (int h = 0; h < theObjectChunks.Length; h++) {
if (theObjectChunks[h] != null) {
finalResult[h] = ((AbstractKModel) selfPointer._manager.model()).createProxy(universe, time, uuids[h], selfPointer._manager.model().metaModel().metaClass(((KObjectChunk) theObjectChunks[h]).metaClassIndex()), tempObjectTimeTreeKeys[h * 3], tempObjectChunkKeys[h * 3 + 1]);
} else {
finalResult[h] = null;
}
}
selfPointer._spaceManager.registerAll(finalResult);
callback(finalResult);
}
});
});
});
}
});
} catch (Exception e) {
//e.printStackTrace();
}
};
}
public KTask lookupPreciseKeys(long[] keys, KCallback < KObject[] > callback) {
DistortedTimeResolver selfPointer = this;
return () => {
try {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement != null) {
long[] allOrderedKeys = new long[keys.Length * 3];
int insertIndex = 0;
int nbKeys = keys.Length / 3;
for (int i = 0; i < nbKeys; i++) {
//objectUniverseOrder
allOrderedKeys[insertIndex] = KConfig.NULL_LONG;
insertIndex++;
allOrderedKeys[insertIndex] = KConfig.NULL_LONG;
insertIndex++;
allOrderedKeys[insertIndex] = keys[i * 3 + 2];
insertIndex++;
//objectTimeORder
allOrderedKeys[insertIndex] = keys[i * 3];
insertIndex++;
allOrderedKeys[insertIndex] = KConfig.NULL_LONG;
insertIndex++;
allOrderedKeys[insertIndex] = keys[i * 3 + 2];
insertIndex++;
//objectChunk
allOrderedKeys[insertIndex] = keys[i * 3];
insertIndex++;
allOrderedKeys[insertIndex] = keys[i * 3 + 1];
insertIndex++;
allOrderedKeys[insertIndex] = keys[i * 3 + 2];
insertIndex++;
}
selfPointer.getOrLoadAndMarkAll(allOrderedKeys, (kChunks) => {
if (kChunks == null || kChunks.Length == 0) {
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
} else {
KObject[] finalResult = new KObject[nbKeys];
int insertIndex1 = 0;
int previousClassIndex = -1;
foreach(KChunk kChunk in kChunks) {
if (kChunk != null && kChunk.type() == KChunkTypes.OBJECT_CHUNK) {
finalResult[insertIndex1] = ((AbstractKModel) selfPointer._manager.model()).createProxy(kChunk.universe(), kChunk.time(), kChunk.obj(), selfPointer._manager.model().metaModel().metaClass(previousClassIndex), kChunk.universe(), kChunk.time());
insertIndex1++;
} else if (kChunk != null && kChunk.type() == KChunkTypes.LONG_LONG_MAP) {
KLongLongMap casted = (KLongLongMap) kChunk;
previousClassIndex = casted.metaClassIndex();
}
}
selfPointer._spaceManager.registerAll(finalResult);
callback(finalResult);
}
});
}
});
} catch (Exception e) {
//e.printStackTrace();
}
};
}
public KTask lookupPrepared(KPreparedLookup preparedLookup, KCallback < KObject[] > callback) {
DistortedTimeResolver selfPointer = this;
int nbObjs = preparedLookup.flatLookup().Length / 3;
long[] flat = preparedLookup.flatLookup();
return () => {
try {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement != null) {
long[] tempObjectUniverseKeys = new long[nbObjs * 3];
for (int i = 0; i < nbObjs; i++) {
tempObjectUniverseKeys[i * 3] = KConfig.NULL_LONG;
tempObjectUniverseKeys[i * 3 + 1] = KConfig.NULL_LONG;
tempObjectUniverseKeys[i * 3 + 2] = flat[i * 3 + 2];
}
selfPointer.getOrLoadAndMarkAll(tempObjectUniverseKeys, (objectUniverseOrderElements) => {
if (objectUniverseOrderElements == null || objectUniverseOrderElements.Length == 0) {
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
return;
}
long[] tempObjectTimeTreeKeys = new long[nbObjs * 3];
for (int i = 0; i < nbObjs; i++) {
long closestUniverse = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) objectUniverseOrderElements[i], flat[i * 3 + 1], flat[i * 3]);
tempObjectTimeTreeKeys[i * 3] = closestUniverse;
tempObjectTimeTreeKeys[i * 3 + 1] = KConfig.NULL_LONG;
tempObjectTimeTreeKeys[i * 3 + 2] = flat[i * 3 + 2];
}
selfPointer.getOrLoadAndMarkAll(tempObjectTimeTreeKeys, (objectTimeTreeElements) => {
if (objectTimeTreeElements == null || objectTimeTreeElements.Length == 0) {
selfPointer._spaceManager.unmarkAllMemoryElements(objectUniverseOrderElements);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
return;
}
long[] tempObjectChunkKeys = new long[nbObjs * 3];
for (int i = 0; i < nbObjs; i++) {
long closestTime = ((KLongTree) objectTimeTreeElements[i]).previousOrEqual(flat[i * 3 + 1]);
if (closestTime != KConfig.NULL_LONG) {
tempObjectChunkKeys[i * 3] = tempObjectTimeTreeKeys[i * 3];
tempObjectChunkKeys[i * 3 + 1] = closestTime;
tempObjectChunkKeys[i * 3 + 2] = flat[i * 3 + 2];
} else {
// TODO System.arraycopy(KContentKey.NULL_KEY, 0, tempObjectChunkKeys, (i * 3), 3);
}
}
selfPointer.getOrLoadAndMarkAll(tempObjectChunkKeys, (theObjectChunks) => {
if (theObjectChunks == null || theObjectChunks.Length == 0) {
selfPointer._spaceManager.unmarkAllMemoryElements(objectTimeTreeElements);
selfPointer._spaceManager.unmarkAllMemoryElements(objectUniverseOrderElements);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(new KObject[0]);
} else {
KObject[] finalResult = new KObject[nbObjs];
for (int h = 0; h < theObjectChunks.Length; h++) {
if (theObjectChunks[h] != null) {
finalResult[h] = ((AbstractKModel) selfPointer._manager.model()).createProxy(flat[h * 3], flat[h * 3 + 1], flat[h * 3 + 2], selfPointer._manager.model().metaModel().metaClass(((KObjectChunk) theObjectChunks[h]).metaClassIndex()), tempObjectTimeTreeKeys[h * 3], tempObjectChunkKeys[h * 3 + 1]);
} else {
finalResult[h] = null;
}
}
selfPointer._spaceManager.registerAll(finalResult);
callback(finalResult);
}
});
});
});
}
});
} catch (Exception e) {
//e.printStackTrace();
}
};
}
public KTask lookupAllTimes(long universe, long[] times, long uuid, KCallback < KObject[] > callback) {
DistortedTimeResolver selfPointer = this;
return () => {
try {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement != null) {
selfPointer.getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, uuid, (theObjectUniverseOrderElement) => {
if (theObjectUniverseOrderElement == null) {
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
} else {
long[] closestUniverses = new long[times.Length];
ArrayLongLongMap closestUnikUniverse = new ArrayLongLongMap(-1, -1, -1, null);
int nbUniverseToload = 0;
for (int i = 0; i < times.Length; i++) {
closestUniverses[i] = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) theObjectUniverseOrderElement, times[i], universe);
if (!closestUnikUniverse.contains(closestUniverses[i])) {
closestUnikUniverse.put(closestUniverses[i], nbUniverseToload);
nbUniverseToload++;
}
}
long[] toLoadUniverseKeys = new long[nbUniverseToload * 3];
foreach(var entry in closestUnikUniverse) {
var key = entry.Key;
var value = entry.Value;
int currentIndex = (int)(value * 3);
toLoadUniverseKeys[currentIndex] = value;
toLoadUniverseKeys[currentIndex + 1] = KConfig.NULL_LONG;
toLoadUniverseKeys[currentIndex + 2] = uuid;
}
selfPointer.getOrLoadAndMarkAll(toLoadUniverseKeys, (objectTimeTreeElements) => {
if (objectTimeTreeElements == null || objectTimeTreeElements.Length == 0) {
selfPointer._spaceManager.unmarkMemoryElement(theObjectUniverseOrderElement);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
} else {
long[] closestTimes = new long[times.Length];
ArrayLongLongMap closestUnikTimes = new ArrayLongLongMap(-1, -1, -1, null);
ArrayLongLongMap reverseTimeUniverse = new ArrayLongLongMap(-1, -1, -1, null);
int nbTimesToload = 0;
for (int i = 0; i < times.Length; i++) {
int alignedIndexOfUniverse = (int) closestUnikUniverse.get(closestUniverses[i]);
closestTimes[i] = ((KLongTree) objectTimeTreeElements[alignedIndexOfUniverse]).previousOrEqual(times[i]);
if (!closestUnikTimes.contains(closestTimes[i])) {
closestUnikTimes.put(closestTimes[i], nbTimesToload);
reverseTimeUniverse.put(closestTimes[i], closestUniverses[i]);
nbTimesToload++;
}
}
long[] toLoadTimesKeys = new long[nbTimesToload * 3];
foreach(var entry in closestUnikTimes) {
var key = entry.Key;
var value = entry.Value;
int currentIndex = (int)(value * 3);
toLoadTimesKeys[currentIndex] = reverseTimeUniverse.get(key);
toLoadTimesKeys[currentIndex + 1] = key;
toLoadTimesKeys[currentIndex + 2] = uuid;
}
selfPointer.getOrLoadAndMarkAll(toLoadTimesKeys, (objectChunks) => {
if (objectChunks == null || objectChunks.Length == 0) {
selfPointer._spaceManager.unmarkAllMemoryElements(objectTimeTreeElements);
selfPointer._spaceManager.unmarkMemoryElement(theObjectUniverseOrderElement);
selfPointer._spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
} else {
KObject[] result = new KObject[times.Length];
for (int i = 0; i < times.Length; i++) {
long resolvedUniverse = closestUniverses[i];
long resolvedTime = closestTimes[i];
int indexChunks = (int) closestUnikTimes.get(closestTimes[i]);
if (indexChunks != -1 && resolvedUniverse != KConfig.NULL_LONG && resolvedTime != KConfig.NULL_LONG) {
result[i] = ((AbstractKModel) selfPointer._manager.model()).createProxy(universe, times[i], uuid, selfPointer._manager.model().metaModel().metaClass(((KObjectChunk) objectChunks[indexChunks]).metaClassIndex()), resolvedUniverse, resolvedTime);
} else {
result[i] = null;
}
}
selfPointer._spaceManager.registerAll(result);
callback(result);
}
});
}
});
}
});
}
});
} catch (Exception e) {
//e.printStackTrace();
}
};
}
public KObjectChunk preciseChunk(long universe, long time, long uuid, KMetaClass metaClass, AtomicReference < long[] > previousResolution) {
return internal_chunk(universe, time, uuid, false, metaClass, previousResolution);
}
public KObjectChunk closestChunk(long universe, long time, long uuid, KMetaClass metaClass, AtomicReference < long[] > previousResolution) {
return internal_chunk(universe, time, uuid, true, metaClass, previousResolution);
}
//TODO optimize the worst case by reusing, by using previous universe cache information, maybe optimize
//FIXME
private KObjectChunk internal_chunk(long universe, long requestedTime, long uuid, bool useClosest, KMetaClass metaClass, AtomicReference < long[] > previousResolution) {
long time = requestedTime;
if (metaClass.temporalResolution() != 1) {
time = time - (time % metaClass.temporalResolution());
}
KObjectChunk currentEntry = (KObjectChunk) _spaceManager.getAndMark(universe, time, uuid);
if (currentEntry != null) {
long[] previous;
long[] current;
bool diff = false;
do {
previous = previousResolution.get();
if (previous[AbstractKObject.UNIVERSE_PREVIOUS_INDEX] != universe || previous[AbstractKObject.TIME_PREVIOUS_INDEX] != time) {
current = new long[] {
universe, time
};
diff = true;
} else {
current = previous;
}
} while (!previousResolution.compareAndSet(previous, current));
if (diff) {
//we obtains the token, and we have to free the previous one, the new one stay marked
_spaceManager.unmark(previous[AbstractKObject.UNIVERSE_PREVIOUS_INDEX], previous[AbstractKObject.TIME_PREVIOUS_INDEX], uuid);
} else {
_spaceManager.unmarkMemoryElement(currentEntry);
}
return currentEntry;
}
KLongLongMap objectUniverseTree = (KLongLongMap) _spaceManager.getAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, uuid);
if (objectUniverseTree == null) {
return null;
}
KLongLongMap globalUniverseTree = (KLongLongMap) _spaceManager.getAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG);
if (globalUniverseTree == null) {
_spaceManager.unmarkMemoryElement(objectUniverseTree);
return null;
}
long resolvedUniverse = resolve_universe(globalUniverseTree, objectUniverseTree, time, universe);
KLongTree timeTree = (KLongTree) _spaceManager.getAndMark(resolvedUniverse, KConfig.NULL_LONG, uuid);
if (timeTree == null) {
_spaceManager.unmarkMemoryElement(globalUniverseTree);
_spaceManager.unmarkMemoryElement(objectUniverseTree);
return null;
}
long resolvedTime = timeTree.previousOrEqual(time);
if (resolvedTime != KConfig.NULL_LONG) {
bool needTimeCopy = !useClosest && (resolvedTime != time);
bool needUniverseCopy = !useClosest && (resolvedUniverse != universe);
currentEntry = (KObjectChunk) _spaceManager.getAndMark(resolvedUniverse, resolvedTime, uuid);
if (currentEntry == null) {
//TODO cache miss here, we unMark everything used Chunk and go out
//System.err.println("DePhasing problem, null chunk unexpected");
_spaceManager.unmarkMemoryElement(timeTree);
_spaceManager.unmarkMemoryElement(globalUniverseTree);
_spaceManager.unmarkMemoryElement(objectUniverseTree);
return null;
}
if (!needTimeCopy && !needUniverseCopy) {
long[] previous;
long[] current;
bool diff = false;
do {
previous = previousResolution.get();
if (previous[AbstractKObject.UNIVERSE_PREVIOUS_INDEX] != resolvedUniverse || previous[AbstractKObject.TIME_PREVIOUS_INDEX] != resolvedTime) {
current = new long[] {
resolvedUniverse, resolvedTime
};
diff = true;
} else {
current = previous;
}
} while (!previousResolution.compareAndSet(previous, current));
if (diff) {
//we obtains the token, and we have to free the previous one
_spaceManager.unmark(previous[AbstractKObject.UNIVERSE_PREVIOUS_INDEX], previous[AbstractKObject.TIME_PREVIOUS_INDEX], uuid);
} else {
_spaceManager.unmarkMemoryElement(currentEntry);
}
_spaceManager.unmarkMemoryElement(timeTree);
_spaceManager.unmarkMemoryElement(globalUniverseTree);
_spaceManager.unmarkMemoryElement(objectUniverseTree);
return currentEntry;
} else {
long[] previous;
long[] current;
bool diff = false;
do {
previous = previousResolution.get();
if (previous[AbstractKObject.UNIVERSE_PREVIOUS_INDEX] != universe || previous[AbstractKObject.TIME_PREVIOUS_INDEX] != time) {
current = new long[] {
universe, time
};
diff = true;
} else {
current = previous;
}
} while (!previousResolution.compareAndSet(previous, current));
if (diff) {
KObjectChunk clonedChunk = _spaceManager.cloneAndMark(currentEntry, universe, time, uuid, _manager.model().metaModel());
if (currentEntry.counter() > 2) { //test if we are alone on this chunk or not
//double marking strategy
currentEntry.addDependency(universe, time, uuid);
_spaceManager.markMemoryElement(clonedChunk);
}
if (!needUniverseCopy) {
timeTree.insertKey(time);
} else {
KLongTree newTemporalTree = (KLongTree) _spaceManager.createAndMark(universe, KConfig.NULL_LONG, uuid, KChunkTypes.LONG_TREE);
newTemporalTree.insertKey(time);
_spaceManager.unmarkMemoryElement(timeTree);
objectUniverseTree.put(universe, time);
}
//double unmarking, because, we should not use anymore this object
_spaceManager.unmarkMemoryElement(currentEntry);
_spaceManager.unmarkMemoryElement(currentEntry);
//free the rest of used object
_spaceManager.unmarkMemoryElement(timeTree);
_spaceManager.unmarkMemoryElement(globalUniverseTree);
_spaceManager.unmarkMemoryElement(objectUniverseTree);
return clonedChunk;
} else {
//System.err.println("Should not be here !!!!");
_spaceManager.unmarkMemoryElement(timeTree);
_spaceManager.unmarkMemoryElement(globalUniverseTree);
_spaceManager.unmarkMemoryElement(objectUniverseTree);
KObjectChunk waitingChunk = (KObjectChunk) _spaceManager.getAndMark(universe, time, uuid);
int i = 0;
while (waitingChunk == null && i < KConfig.CAS_MAX_TRY) {
waitingChunk = (KObjectChunk) _spaceManager.getAndMark(universe, time, uuid);
i++;
}
if (waitingChunk == null) {
throw new Exception("CAS synchronisation problem!");
} else {
_spaceManager.unmarkMemoryElement(currentEntry);
return waitingChunk;
}
}
}
} else {
_spaceManager.unmarkMemoryElement(timeTree);
_spaceManager.unmarkMemoryElement(globalUniverseTree);
_spaceManager.unmarkMemoryElement(objectUniverseTree);
return null;
}
}
public void indexObject(KObject obj) {
int metaClassIndex = obj.metaClass().index();
KObjectChunk cacheEntry = (KObjectChunk) _spaceManager.createAndMark(obj.universe(), obj.now(), obj.uuid(), KChunkTypes.OBJECT_CHUNK);
cacheEntry.init(null, _manager.model().metaModel(), metaClassIndex);
cacheEntry.setFlags(KChunkFlags.DIRTY_BIT, 0);
cacheEntry.space().declareDirty(cacheEntry);
//initiate time management
KLongTree timeTree = (KLongTree) _spaceManager.createAndMark(obj.universe(), KConfig.NULL_LONG, obj.uuid(), KChunkTypes.LONG_TREE);
timeTree.init(null, _manager.model().metaModel(), metaClassIndex);
timeTree.insertKey(obj.now());
//initiate universe management
KLongLongMap universeTree = (KLongLongMap) _spaceManager.createAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, obj.uuid(), KChunkTypes.LONG_LONG_MAP);
universeTree.init(null, _manager.model().metaModel(), metaClassIndex);
universeTree.put(obj.universe(), obj.now());
_spaceManager.register(obj);
}
public short typeFromKey(long universe, long time, long uuid) {
bool isUniverseNotNull = universe != KConfig.NULL_LONG;
short result;
if (KConfig.END_OF_TIME == uuid) {
if (isUniverseNotNull) {
result = KChunkTypes.LONG_LONG_TREE;
} else {
result = KChunkTypes.LONG_LONG_MAP;
}
} else {
bool isTimeNotNull = time != KConfig.NULL_LONG;
bool isObjNotNull = uuid != KConfig.NULL_LONG;
if (isUniverseNotNull && isTimeNotNull && isObjNotNull) {
result = KChunkTypes.OBJECT_CHUNK;
} else if (isUniverseNotNull && !isTimeNotNull && isObjNotNull) {
result = KChunkTypes.LONG_TREE;
} else {
result = KChunkTypes.LONG_LONG_MAP;
}
}
return result;
}
public void getOrLoadAndMark(long universe, long time, long uuid, KCallback < KChunk > callback) {
if (universe == KContentKey.NULL_KEY[0] && time == KContentKey.NULL_KEY[1] && uuid == KContentKey.NULL_KEY[2]) {
callback(null);
return;
}
KChunk cached = _spaceManager.getAndMark(universe, time, uuid);
if (cached != null) {
callback(cached);
} else {
load(new long[] {
universe, time, uuid
}, (loadedElements) => callback(loadedElements[0]));
}
}
public void getOrLoadAndMarkAll(long[] keys, KCallback < KChunk[] > callback) {
int nbKeys = keys.Length / KEYS_SIZE;
bool[] toLoadIndexes = new bool[nbKeys];
int nbElem = 0;
KChunk[] result = new KChunk[nbKeys];
for (int i = 0; i < nbKeys; i++) {
if (keys[i * KEYS_SIZE] == KContentKey.NULL_KEY[0] && keys[i * KEYS_SIZE + 1] == KContentKey.NULL_KEY[1] && keys[i * KEYS_SIZE + 2] == KContentKey.NULL_KEY[2]) {
toLoadIndexes[i] = false;
result[i] = null;
} else {
result[i] = _spaceManager.getAndMark(keys[i * KEYS_SIZE], keys[i * KEYS_SIZE + 1], keys[i * KEYS_SIZE + 2]);
if (result[i] == null) {
toLoadIndexes[i] = true;
nbElem++;
} else {
toLoadIndexes[i] = false;
}
}
}
if (nbElem == 0) {
callback(result);
} else {
long[] keysToLoad = new long[nbElem * 3];
int lastInsertedIndex = 0;
for (int i = 0; i < nbKeys; i++) {
if (toLoadIndexes[i]) {
keysToLoad[lastInsertedIndex] = keys[i * KEYS_SIZE];
lastInsertedIndex++;
keysToLoad[lastInsertedIndex] = keys[i * KEYS_SIZE + 1];
lastInsertedIndex++;
keysToLoad[lastInsertedIndex] = keys[i * KEYS_SIZE + 2];
lastInsertedIndex++;
}
}
load(keysToLoad, (KChunk[] loadedElements) => {
int currentIndexToMerge = 0;
for (int i = 0; i < nbKeys; i++) {
if (toLoadIndexes[i]) {
result[i] = loadedElements[currentIndexToMerge];
currentIndexToMerge++;
}
}
callback(result);
});
}
}
public void getIndex(String metaClassName, long universe, long time, Object[] attrs, KCallback < KObject > callback) {
long rootFixedKey = KConfig.END_OF_TIME;
getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (KChunk theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement == null) {
callback(null);
return;
}
getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, rootFixedKey, (KChunk rootGlobalUniverseOrderElement) => {
if (rootGlobalUniverseOrderElement == null) {
_spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
return;
}
long closestUniverse = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) rootGlobalUniverseOrderElement, time, universe);
getOrLoadAndMark(closestUniverse, KConfig.NULL_LONG, rootFixedKey, (KChunk theRootTimeTree) => {
long resolvedCurrentRootUUID = ((KLongLongTree) theRootTimeTree).previousOrEqualValue(time);
_spaceManager.unmarkMemoryElement(theRootTimeTree);
_spaceManager.unmarkMemoryElement(rootGlobalUniverseOrderElement);
_spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
if (resolvedCurrentRootUUID == KConfig.NULL_LONG) {
callback(null);
} else {
_manager.lookup(universe, time, resolvedCurrentRootUUID, callback);
}
});
});
});
}
//TODO, ROOT TREE is NEVER UNLOAD
public void getRoot(long universe, long time, KCallback < KObject > callback) {
long rootFixedKey = KConfig.END_OF_TIME;
getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (KChunk theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement == null) {
callback(null);
return;
}
getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, rootFixedKey, (KChunk rootGlobalUniverseOrderElement) => {
if (rootGlobalUniverseOrderElement == null) {
_spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
callback(null);
return;
}
long closestUniverse = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) rootGlobalUniverseOrderElement, time, universe);
getOrLoadAndMark(closestUniverse, KConfig.NULL_LONG, rootFixedKey, (KChunk theRootTimeTree) => {
long resolvedCurrentRootUUID = ((KLongLongTree) theRootTimeTree).previousOrEqualValue(time);
_spaceManager.unmarkMemoryElement(theRootTimeTree);
_spaceManager.unmarkMemoryElement(rootGlobalUniverseOrderElement);
_spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
if (resolvedCurrentRootUUID == KConfig.NULL_LONG) {
callback(null);
} else {
_manager.lookup(universe, time, resolvedCurrentRootUUID, callback);
}
});
});
});
}
public void setRoot(KObject newRoot, KCallback < Throwable > callback) {
long rootFixedKey = KConfig.END_OF_TIME;
getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG, (KChunk theGlobalUniverseOrderElement) => {
if (theGlobalUniverseOrderElement == null) {
callback(null);
return;
}
getOrLoadAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, rootFixedKey, (KChunk rootGlobalUniverseOrderElement) => {
KLongLongMap rootGlobalUniverseOrder = (KLongLongMap) rootGlobalUniverseOrderElement;
if (rootGlobalUniverseOrderElement == null) {
rootGlobalUniverseOrder = (KLongLongMap) _spaceManager.createAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.END_OF_TIME, KChunkTypes.LONG_LONG_MAP);
}
long closestUniverse = resolve_universe((KLongLongMap) theGlobalUniverseOrderElement, (KLongLongMap) rootGlobalUniverseOrderElement, newRoot.now(), newRoot.universe());
rootGlobalUniverseOrder.put(newRoot.universe(), newRoot.now());
if (closestUniverse != newRoot.universe()) {
KLongLongTree newTimeTree = (KLongLongTree) _spaceManager.createAndMark(newRoot.universe(), KConfig.NULL_LONG, KConfig.END_OF_TIME, KChunkTypes.LONG_LONG_TREE);
newTimeTree.insert(newRoot.now(), newRoot.uuid());
_spaceManager.unmarkMemoryElement(newTimeTree);
_spaceManager.unmarkMemoryElement(rootGlobalUniverseOrderElement);
_spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
if (callback != null) {
callback(null);
}
} else {
getOrLoadAndMark(closestUniverse, KConfig.NULL_LONG, KConfig.END_OF_TIME, (KChunk resolvedRootTimeTree) => {
KLongLongTree initializedTree = (KLongLongTree) resolvedRootTimeTree;
if (initializedTree == null) {
initializedTree = (KLongLongTree) _spaceManager.createAndMark(closestUniverse, KConfig.NULL_LONG, KConfig.END_OF_TIME, KChunkTypes.LONG_LONG_TREE);
}
initializedTree.insert(newRoot.now(), newRoot.uuid());
_spaceManager.unmarkMemoryElement(resolvedRootTimeTree);
_spaceManager.unmarkMemoryElement(rootGlobalUniverseOrderElement);
_spaceManager.unmarkMemoryElement(theGlobalUniverseOrderElement);
if (callback != null) {
callback(null);
}
});
}
});
});
}
public void resolveTimes(long currentUniverse, long currentUuid, long startTime, long endTime, KCallback < long[] > callback) {
long[] keys = new long[] {
KConfig.NULL_LONG, KConfig.NULL_LONG, KConfig.NULL_LONG,
KConfig.NULL_LONG, KConfig.NULL_LONG, currentUuid
};
getOrLoadAndMarkAll(keys, (KChunk[] kMemoryChunks) => {
if (kMemoryChunks == null || kMemoryChunks.Length == 0) {
callback(new long[0]);
return;
}
long[] collectedUniverse = universeSelectByRange((KLongLongMap) kMemoryChunks[0], (KLongLongMap) kMemoryChunks[1], startTime, endTime, currentUniverse);
int nbKeys = collectedUniverse.Length * 3;
long[] timeTreeKeys = new long[nbKeys];
for (int i = 0; i < collectedUniverse.Length; i++) {
timeTreeKeys[i * 3] = collectedUniverse[i];
timeTreeKeys[i * 3 + 1] = KConfig.NULL_LONG;
timeTreeKeys[i * 3 + 2] = currentUuid;
}
KLongLongMap objUniverse = (KLongLongMap) kMemoryChunks[1];
getOrLoadAndMarkAll(timeTreeKeys, (KChunk[] timeTrees) => {
if (timeTrees == null || timeTrees.Length == 0) {
_spaceManager.unmarkAllMemoryElements(kMemoryChunks);
callback(new long[0]);
return;
}
ArrayLongLongMap collector = new ArrayLongLongMap(-1, -1, -1, null);
long previousDivergenceTime = endTime;
for (int i = 0; i < collectedUniverse.Length; i++) {
KLongTree timeTree = (KLongTree) timeTrees[i];
if (timeTree != null) {
long currentDivergenceTime = objUniverse.get(collectedUniverse[i]);
currentDivergenceTime = currentDivergenceTime > startTime ? currentDivergenceTime : startTime;
long finalPreviousDivergenceTime = previousDivergenceTime;
timeTree.range(currentDivergenceTime, previousDivergenceTime, (t) => {
if (collector.size() == 0) {
collector.put(collector.size(), t);
} else {
if (t != finalPreviousDivergenceTime) {
collector.put(collector.size(), t);
}
}
});
previousDivergenceTime = currentDivergenceTime;
}
}
long[] orderedTime = new long[collector.size()];
for (int i = 0; i < collector.size(); i++) {
orderedTime[i] = collector.get(i);
}
_spaceManager.unmarkAllMemoryElements(timeTrees);
_spaceManager.unmarkAllMemoryElements(kMemoryChunks);
callback(orderedTime);
});
});
}
public static long resolve_universe(KLongLongMap globalTree, KLongLongMap objUniverseTree, long timeToResolve, long originUniverseId) {
if (globalTree == null || objUniverseTree == null) {
return originUniverseId;
}
long currentUniverse = originUniverseId;
long previousUniverse = KConfig.NULL_LONG;
long divergenceTime = objUniverseTree.get(currentUniverse);
while (currentUniverse != previousUniverse) {
//check range
if (divergenceTime != KConfig.NULL_LONG && divergenceTime <= timeToResolve) {
return currentUniverse;
}
//next round
previousUniverse = currentUniverse;
currentUniverse = globalTree.get(currentUniverse);
divergenceTime = objUniverseTree.get(currentUniverse);
}
return originUniverseId;
}
public static long[] universeSelectByRange(KLongLongMap globalTree, KLongLongMap objUniverseTree, long rangeMin, long rangeMax, long originUniverseId) {
KLongLongMap collected = new ArrayLongLongMap(-1, -1, -1, null);
long currentUniverse = originUniverseId;
long previousUniverse = KConfig.NULL_LONG;
long divergenceTime = objUniverseTree.get(currentUniverse);
while (currentUniverse != previousUniverse) {
//check range
if (divergenceTime != KConfig.NULL_LONG) {
if (divergenceTime <= rangeMin) {
collected.put(collected.size(), currentUniverse);
break;
} else if (divergenceTime <= rangeMax) {
collected.put(collected.size(), currentUniverse);
}
}
//next round
previousUniverse = currentUniverse;
currentUniverse = globalTree.get(currentUniverse);
divergenceTime = objUniverseTree.get(currentUniverse);
}
long[] trimmed = new long[collected.size()];
for (long i = 0; i < collected.size(); i++) {
trimmed[(int) i] = collected.get(i);
}
return trimmed;
}
private void load(long[] keys, KCallback < KChunk[] > callback) {
this._manager.cdn().get(keys, (payloads) => {
KChunk[] results = new KChunk[keys.Length / 3];
for (int i = 0; i < payloads.Length; i++) {
long loopUniverse = keys[i * 3];
long loopTime = keys[i * 3 + 1];
long loopUuid = keys[i * 3 + 2];
results[i] = _spaceManager.createAndMark(loopUniverse, loopTime, loopUuid, typeFromKey(loopUniverse, loopTime, loopUuid));
int classIndex = -1;
if (loopUniverse != KConfig.NULL_LONG && loopTime != KConfig.NULL_LONG && loopUuid != KConfig.NULL_LONG) {
KLongLongMap alreadyLoadedOrder = (KLongLongMap) _spaceManager.getAndMark(KConfig.NULL_LONG, KConfig.NULL_LONG, loopUuid);
if (alreadyLoadedOrder != null) {
classIndex = alreadyLoadedOrder.metaClassIndex();
_spaceManager.unmarkMemoryElement(alreadyLoadedOrder);
}
}
results[i].init(payloads[i], _manager.model().metaModel(), classIndex);
}
callback(results);
});
}
public int getRelatedKeysResultSize() {
return 4;
}
public void getRelatedKeys(long universe, long time, long uuid, long[] result) {
result[0] = universe;
result[1] = time;
result[2] = uuid;
result[3] = universe;
result[4] = KConfig.NULL_LONG;
result[5] = uuid;
result[6] = KConfig.NULL_LONG;
result[7] = KConfig.NULL_LONG;
result[8] = uuid;
result[9] = KConfig.NULL_LONG;
result[10] = KConfig.NULL_LONG;
result[11] = KConfig.NULL_LONG;
}
}
}
using System;
namespace test
{
public delegate void KCallback<T>(T p);
}
using System;
namespace test
{
public delegate void KTask();
}
using System;
namespace test
{
public delegate void KTreeWalker(long t);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment