Skip to content
Snippets Groups Projects
Commit 164df670 authored by Sebastian Ebert's avatar Sebastian Ebert
Browse files

initial parallel rsync contribution

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 1271 additions and 0 deletions
package org.rosi_project.model_management.sync
import org.rosi_project.model_management.sync.roles.IRoleManager
import scroll.internal.MultiCompartment
/**
* PART OF RSYNC-CORE by Christopher Werner (TUD)
* Interface for the synchronization management compartment.
*/
trait ISynchronizationCompartment extends MultiCompartment {
protected var underConstruction: Boolean = false
/**
* Is currently in a process where new elements could be created.
*/
def isUnderConstruction(): Boolean = underConstruction
/**
* Get a new RoleManager instance.
*/
def createRoleManager(): IRoleManager
}
package org.rosi_project.model_management.sync.compartments
import org.rosi_project.model_management.core.PlayerSync
import org.rosi_project.model_management.sync.IDestructionCompartment
import org.rosi_project.model_management.sync.roles.{ IDestructor, IRoleManager }
import scala.collection.mutable.ListBuffer
import org.rosi_project.model_management.core.ModelElementLists
/**
* PART OF RSYNC-CORE by Christopher Werner (TUD)
* Calls the destruction method from all related RoleManagers and then deletes all roles from this player.
*/
object GeneralDestructor extends IDestructionCompartment {
override def getDestructorForClassName(classname: Object): IDestructor = new DeleteRole
override def getRuleName: String = "GeneralDestructor"
class DeleteRole() extends IDestructor {
def deleteRoleFunction(): Unit = {
//remove this manager from all related ones
+this removeThisManager()
//clear list of related manager
+this clearRelatedManager()
//send notification about deletion
+this deletionNotification()
//delete all roles this element has
val player = this.player
if (player.isRight) {
val test: PlayerSync = player.right.get.asInstanceOf[PlayerSync]
ModelElementLists.removeElement(test)
val roles = test.roles()
roles.foreach { r =>
r.remove()
}
}
}
}
class DeleteRoleAndConnections() extends IDestructor {
def deleteRoleFunction(): Unit = {
//get the list of related manager
var relatedManagers: Set[IRoleManager] = (+this).getRelatedManager()
//clear all lists from the related managers
(+this).clearListsOfRelatedManager()
//delete also all related elements
relatedManagers.foreach { m =>
(+m).deleteObjectFromSynchro()
}
//send notification about deletion
(+this).deletionNotification()
//clear now the related manager list
(+this).clearRelatedManager()
//delete all roles this element has
val player = this.player
if (player.isRight) {
val test: PlayerSync = player.right.get.asInstanceOf[PlayerSync]
ModelElementLists.removeElement(test)
val roles = test.roles()
roles.foreach { r =>
r.remove()
}
}
}
}
}
package org.rosi_project.model_management.sync.compartments
import org.rosi_project.model_management.core.ModelElementLists
import org.rosi_project.model_management.sync.IExtenstionCompartment
import org.rosi_project.model_management.sync.roles.IExtension
import scroll.internal.errors.SCROLLErrors.TypeError
/**
* PART OF RSYNC-CORE by Christopher Werner (TUD)
* Extension to delete instances which are removed from the synchronization context from the
* [[ModelElementLists]]. This extension therefore functions as some kind of garbage collector,
* hence the name.
*
* @author Rico Bergmann
*/
object ModelElementsListGCExtension extends IExtenstionCompartment {
/**
* Return a role instance that handles the extension process for the object.
*/
override def getExtensionForClassName(classname: Object): IExtension = new GarbageCollector
/**
* Return a unique name that describes this extension.
*/
override def getExtensionName(): String = "ModelElementsList GarbageCollector"
/** The actual extension.
*/
class GarbageCollector extends IExtension {
/**
* Function to react on insertion behavior.
*/
override def notifyInsertion(): Unit = {
;
}
/**
* Function to react on deletion behavior.
*/
override def notifyDeletion(): Unit = {
val player: Either[TypeError, AnyRef] = this.player
player.right.foreach { obj =>
println(s"Removing $obj")
ModelElementLists.removeElement(obj)
}
}
/**
* Function to react on update behavior.
*/
override def notifyUpdate(): Unit = {
;
}
}
}
package org.rosi_project.model_management.sync.compartments
import org.rosi_project.model_management.core.{PlayerSync, SynchronizationCompartment}
import org.rosi_project.model_management.sync.IConstructionCompartment
import org.rosi_project.model_management.sync.roles.{IConstructor, IRoleManager}
/**
* PART OF RSYNC-CORE by Christopher Werner (TUD)
* An [[IConstructionCompartment]] which will not create any related instances in other models
*
* @author Rico Bergmann
*/
object SuppressingConstructionCompartment extends IConstructionCompartment {
override def getConstructorForClassName(classname: Object): IConstructor = new Suppressor
override def getRuleName: String = "SuppressingConstructionCompartment"
/** The constructor will only create the necessary `plays` relationships with the synchronization
* services
*/
class Suppressor extends IConstructor {
override def construct(comp: PlayerSync, man: IRoleManager): Unit = {
// just set up the player
createContainerElement(start=true, con=true, comp, man)
makeCompleteConstructionProcess(containers)
}
}
}
package org.rosi_project.model_management.sync.conflict.customrules
import org.rosi_project.model_management.core.PlayerSync
import scala.collection.mutable.ListBuffer
import org.slf4j.LoggerFactory
/**
* Allows the execution of a row custom rules combined by logical OR / AND.
*/
object CustomRuleExecutor {
private val logger = LoggerFactory.getLogger(CustomRuleExecutor.getClass)
private var refRules: ListBuffer[ICustomReferenceRule] = new ListBuffer[ICustomReferenceRule]()
private var deletionRules: ListBuffer[ICustomDeletionRule] = new ListBuffer[ICustomDeletionRule]()
/**
* returns all custom reference rules
*/
def getRefRules(): ListBuffer[ICustomReferenceRule] = {
return refRules
}
/**
* returns all custom deletion rules
*/
def getDeletionRules(): ListBuffer[ICustomDeletionRule] = {
return deletionRules
}
/**
* logs out all rules that the CustomRuleExecutor knows
*/
def logRules(): Unit = {
logger.debug("*** Custom Reference Rules:")
refRules.foreach{ r =>
logger.debug("****** " + r.getRuleName())
}
logger.debug("*** Custom Deletion Rules:")
deletionRules.foreach{ r =>
logger.debug("****** " + r.getRuleName())
}
}
/**
* adds a custom deletion rule to the CustomRuleExecutor
*/
def addCustomDeletionRule(rule: ICustomDeletionRule): Unit = {
deletionRules.foreach { r =>
if (r.getRuleName() == rule.getRuleName()) {
return
}
}
deletionRules += rule
}
/**
* removes a custom deletion rule from the CustomRuleExecutor
*/
def removeCustomDeletionRule(ruleName: String): Unit = {
deletionRules.foreach { r =>
if (r.getRuleName() == ruleName) {
deletionRules -= r
return
}
}
}
/**
* adds a custom reference rule to the CustomRuleExecutor
*/
def addCustomReferenceRule(rules: ICustomReferenceRule*): Unit = {
rules.foreach { rule =>
refRules.foreach { r =>
if (r.getRuleName() == rule.getRuleName()) {
return
}
}
refRules += rule
}
}
/**
* removes a custom reference rule from the CustomRuleExecutor
*/
def removeCustomReferenceRule(ruleName: String): Unit = {
refRules.foreach { r =>
if (r.getRuleName() == ruleName) {
refRules -= r
return
}
}
}
/**
* applies reference rules (connected with logical AND)
*/
def matchesAllCustomReferenceRules(referencingElement: PlayerSync, referencedElement: PlayerSync, senderRv: Int, isDeletion: Boolean, senderOwner: String, collection: String): Boolean = {
refRules.foreach { r =>
if (r.isReferenceDeletionRule() == isDeletion) {
logger.info("####### Executing rule: " + r.getRuleName())
if (!r.matchesRule(referencingElement, referencedElement, senderRv, senderOwner, collection)) {
return false
}
}
}
return true
}
/**
* applies reference rules (connected with logical OR)
*/
def matchesMinOneCustomReferenceRule(referencingElement: PlayerSync, referencedElement: PlayerSync, senderRv: Int,
isDeletion: Boolean, senderOwner: String, collection: String): Boolean = {
if (refRules.isEmpty) {
return true
}
refRules.foreach { r =>
if (r.isReferenceDeletionRule() == isDeletion) {
if (r.matchesRule(referencingElement, referencedElement, senderRv, senderOwner, collection)) {
return true
}
}
}
return false
}
/**
* applies deletion rules (connected with logical AND)
*/
def matchesAllCustomDeletionRules(element: PlayerSync, senderOwner: String): Boolean = {
deletionRules.foreach { r =>
if (!r.matchesRule(element, senderOwner)) {
return false
}
}
return true
}
/**
* applies deletion rules (connected with logical OR)
*/
def matchesMinOneCustomDeletionRule(element: PlayerSync, senderOwner: String): Boolean = {
if (refRules.size == 0) {
return true
}
deletionRules.foreach { r =>
if (r.matchesRule(element, senderOwner)) {
return true
}
}
return false
}
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.customrules
import org.rosi_project.model_management.core.PlayerSync
/**
* Interface for all custom deletion-rules.
*/
trait ICustomDeletionRule {
/**
* get name of this rule
*/
def getRuleName(): String
/**
* true if element matches the rule
*/
def matchesRule(element: PlayerSync, senderOwner: String): Boolean
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.customrules
import org.rosi_project.model_management.core.PlayerSync
/**
* Interface for all custom reference-rules.
*/
trait ICustomReferenceRule {
/**
* get name of this rule
*/
def getRuleName(): String
/**
* flag that defines if its a reference-creation- or a reference-deletion-rule
*/
def isReferenceDeletionRule(): Boolean
/**
* true if referencing / referenced element matches the rule
*/
def matchesRule(referencingElement: PlayerSync, referencedElement: PlayerSync, senderRv: Int, senderOwner: String, collection: String): Boolean
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.systemrules
import org.rosi_project.model_management.core.PlayerSync
/**
* Interface for all system-rules for data-changes (modification and deletions).
*/
trait DataConflictSystemRule {
/**
* returns the rule name
*/
def getRuleName(): String
/**
* returns true + target-element, if rule detects no modification-conflict
*/
def resolveModificationConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync)
/**
* returns true + target-element, if rule detects no deletion-conflict
*/
def resolveDeletionConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync)
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.systemrules
import org.rosi_project.model_management.core.PlayerSync
import org.rosi_project.model_management.core.ModelElementLists
import org.rosi_project.model_management.sync.lock._
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* Data-conflict-system-rule which integrates the owner mechanism.
*/
@SystemRule("data")
class OwnerDataConflictSystemRule extends DataConflictSystemRule {
val logger = LoggerFactory.getLogger(classOf[OwnerDataConflictSystemRule])
def getRuleName() = "OwnerDataConflictSystemRule"
def resolveModificationConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync) = {
var elementSet: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(elementKey)
elementSet.foreach { elem =>
var playerSync: SynchronizationAware = elem.asInstanceOf[SynchronizationAware]
// check for conflicts
if (playerSync.guid == guid) {
if (playerSync.deleted) {
logger.error("Detected deleted element in ModelElementsList ... this should not occur!")
}
// check if mod-mod-conflict
if (playerSync.owner != modifier) {
logger.error("Owner-Rule detected conflict (MOD-MOD): " + guid)
return (false, playerSync)
} else {
logger.info("Owner-Rule passed by " + guid)
return (true, playerSync)
}
}
}
logger.error("Owner-Rule detected conflict (DEL-MOD): " + guid)
return (false, null)
}
def resolveDeletionConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync) = {
var elementSet: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(elementKey)
elementSet.foreach { elem =>
var playerSync: SynchronizationAware = elem.asInstanceOf[SynchronizationAware]
if (playerSync.guid == guid) {
if (playerSync.deleted) {
logger.error("Detected deleted element in ModelElementsList ... this should not occur!")
}
// check if mod-del-conflict
if (playerSync.owner != modifier) {
logger.error("Owner-Rule detected conflict (MOD-DEL): " + guid)
return (false, playerSync)
} else {
logger.info("Owner-Rule passed by " + guid)
return (true, playerSync)
}
}
}
logger.error("Owner-Rule detected conflict (DEL-DEL): " + guid)
return (false, null)
}
}
package org.rosi_project.model_management.sync.conflict.systemrules
import org.rosi_project.model_management.core.PlayerSync
/**
* Interface for all reference-conflict-system-rules.
*/
trait ReferenceConflictSystemRule {
/**
* returns the rule name
*/
def getRuleName(): String
// ADD-REF & DEL-REF
/**
* resolves conflicts of type: deleted referenced element
* guid -> id of referenced element
*/
def resolveDeletedReferencedElementConflicts(guid: String, elementKey: String): PlayerSync
// REF-MOD-DEL & REF-MOD-ADD
/**
* resolves conflicts of type: deleted referencing element
* guid -> id of referencing element
*/
def resolveDeletedReferencingElementConflicts(guid: String, elementKey: String): PlayerSync
// REF-COUNTER (replaced by custom rules)
@deprecated
def resolveReferenceCounterConflicts(rv: Int, referencingElement: PlayerSync): Boolean
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.systemrules
/**
* annotation for system-rules, to specify if a rule is a reference- or a data-rule
*/
class SystemRule(resolverType: String) extends scala.annotation.StaticAnnotation{
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.systemrules
import scala.collection.mutable.ListBuffer
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.rosi_project.model_management.core.PlayerSync
case class DeletionDataConflictResolutionResult(wasDeleted: Boolean, sync: PlayerSync)
/**
* Allows the execution of a row system rules combined by logical OR.
*/
object SystemRuleExecutor {
private val logger = LoggerFactory.getLogger(SystemRuleExecutor.getClass)
private var refRules: ListBuffer[ReferenceConflictSystemRule] = new ListBuffer[ReferenceConflictSystemRule]()
private var dataRules: ListBuffer[DataConflictSystemRule] = new ListBuffer[DataConflictSystemRule]()
/**
* returns all system reference rules
*/
def getRefRules(): ListBuffer[ReferenceConflictSystemRule] = {
return refRules
}
/**
* returns all system data rules
*/
def getDataRules(): ListBuffer[DataConflictSystemRule] = {
return dataRules
}
/**
* logs out all rules that the SystemRuleExecutor knows
*/
def logRules(): Unit = {
logger.debug("*** System Reference Rules:")
refRules.foreach{ r =>
logger.debug("****** " + r.getRuleName())
}
logger.debug("*** System Data Rules:")
dataRules.foreach{ r =>
logger.debug("****** " + r.getRuleName())
}
}
/**
* adds a system data rule to the SystemRuleExecutor
*/
def addSystemDataRule(rules: DataConflictSystemRule*): Unit = {
rules.foreach { rule =>
dataRules.foreach { r =>
if (r.getRuleName() == rule.getRuleName()) {
return
}
}
dataRules += rule
}
}
/**
* removes a system data rule from the SystemRuleExecutor
*/
def removeSystemDataRule(ruleName: String): Unit = {
dataRules.foreach { r =>
if (r.getRuleName() == ruleName) {
dataRules -= r
return
}
}
}
/**
* adds a system reference rule to the SystemRuleExecutor
*/
def addSystemReferenceRule(rule: ReferenceConflictSystemRule): Unit = {
refRules.foreach { r =>
if (r.getRuleName() == rule.getRuleName()) {
return
}
}
refRules += rule
}
/**
* removes a system data rule from the SystemRuleExecutor
*/
def removeSystemReferenceRule(ruleName: String): Unit = {
refRules.foreach { r =>
if (r.getRuleName() == ruleName) {
refRules -= r
return
}
}
}
/**
* resolve data-modification-conflicts and returns true + target-element, if a minimum 1 rule detects no conflict
*/
def resolveDataModificationConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync) = {
dataRules.foreach{ r =>
var res: (Boolean, PlayerSync) = r.resolveModificationConflicts(ts, modifier, guid, elementKey)
// logical OR
if(res._1){
return res
}
}
return (false, null)
}
/**
* resolve data-deletion-conflicts and returns true + target-element, if a minimum 1 rule detects no conflict
*/
def resolveDataDeletionConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync) = {
dataRules.foreach{ r =>
var res: (Boolean, PlayerSync) = r.resolveDeletionConflicts(ts, modifier, guid, elementKey)
// logical OR
if(res._1){
return res
}
}
return (false, null)
}
/**
* resolve deleted-referenced-element-conflicts and returns true + target-element, if a minimum 1 rule detects no conflict
*/
def resolveDeletedReferencedElementReferenceConflicts(guid: String, elementKey: String): PlayerSync = {
refRules.foreach{ r =>
var res: PlayerSync = r.resolveDeletedReferencedElementConflicts(guid, elementKey)
// logical OR
if(res != null){
return res
}
}
return null
}
/**
* resolve deleted-referencing-element-conflicts and returns true + target-element, if a minimum 1 rule detects no conflict
*/
def resolveDeletedReferencingElementReferenceConflicts(guid: String, elementKey: String): PlayerSync = {
refRules.foreach{ r =>
var res: PlayerSync = r.resolveDeletedReferencingElementConflicts(guid, elementKey)
// logical OR
if(res != null){
return res
}
}
return null
}
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.systemrules
import org.rosi_project.model_management.core.PlayerSync
import org.rosi_project.model_management.core.ModelElementLists
import org.rosi_project.model_management.sync.lock._
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* Data-conflict-system-rule which integrates the data-version mechanism.
*/
@SystemRule("data")
class TsDataConflictSystemRule extends DataConflictSystemRule {
val logger = LoggerFactory.getLogger(classOf[TsDataConflictSystemRule])
def getRuleName() = "TsDataConflictSystemRule"
def resolveModificationConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync) = {
var elementSet: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(elementKey)
elementSet.foreach { elem =>
var playerSync: SynchronizationAware = elem.asInstanceOf[SynchronizationAware]
// check for conflicts
if (playerSync.guid == guid) {
if (playerSync.deleted) {
logger.error("Detected deleted element in ModelElementsList ... this should not occur!")
}
// check if mod-mod-conflict
if (playerSync.ts > ts) {
logger.error("TS-Rule detected conflict (MOD-MOD): " + guid)
return (false, playerSync)
} else {
logger.info("TS-Rule passed by " + guid)
return (true, playerSync)
}
}
}
logger.error("TS-Rule detected conflict (DEL-MOD): " + guid)
return (false, null)
}
def resolveDeletionConflicts(ts: Int, modifier: String, guid: String, elementKey: String): (Boolean, PlayerSync) = {
var elementSet: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(elementKey)
elementSet.foreach { elem =>
var playerSync: SynchronizationAware = elem.asInstanceOf[SynchronizationAware]
if (playerSync.guid == guid) {
if (playerSync.deleted) {
logger.error("Detected deleted element in ModelElementsList ... this should not occur!")
}
// check if mod-del-conflict
if (playerSync.ts > (ts * (-1))) {
logger.error("TS-Rule detected conflict (MOD-DEL): " + guid)
return (false, playerSync)
} else {
logger.info("TS-Rule passed by " + guid)
return (true, playerSync)
}
}
}
logger.error("TS-Rule detected conflict (DEL-DEL): " + guid)
return (false, null)
}
}
\ No newline at end of file
package org.rosi_project.model_management.sync.conflict.systemrules
import org.rosi_project.model_management.core.PlayerSync
import org.rosi_project.model_management.core.ModelElementLists
import org.rosi_project.model_management.sync.lock._
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* Reference-conflict-system-rule which integrates the reference-version mechanism.
*/
@SystemRule("reference")
class TsReferenceConflictSystemRule extends ReferenceConflictSystemRule {
val logger = LoggerFactory.getLogger(classOf[TsReferenceConflictSystemRule])
def getRuleName() = "TsReferenceConflictSystemRule"
def resolveDeletedReferencedElementConflicts(guid: String, elementKey: String): PlayerSync = {
var elementSet: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(elementKey)
elementSet.foreach { elem =>
var playerSync: SynchronizationAware = elem.asInstanceOf[SynchronizationAware]
// check for conflicts
if (playerSync.guid == guid) {
if (playerSync.deleted) {
logger.warn("Detected deleted element in ModelElementsList ... this should not occur!")
} else {
return playerSync
}
}
}
logger.info("Detected ref-conflict (ADD-REF/DEL-REF): " + guid)
return null
}
def resolveDeletedReferencingElementConflicts(guid: String, elementKey: String): PlayerSync = {
var elementSet: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(elementKey)
elementSet.foreach { elem =>
var playerSync: SynchronizationAware = elem.asInstanceOf[SynchronizationAware]
if (playerSync.guid == guid) {
if (playerSync.deleted) {
logger.warn("Detected deleted element in ModelElementsList ... this should not occur!")
} else {
return playerSync
}
}
}
logger.error("Detected ref-conflict (REF-MOD-DEL/REF-MOD-ADD): " + guid)
return null
}
// true --> we take new refs
@deprecated
def resolveReferenceCounterConflicts(rv: Int, referencingElement: PlayerSync): Boolean = {
// reason for 2nd condition: initially the ref-version of a new element is set to 1
return rv == referencingElement.rv || (rv == 0 && referencingElement.rv == 1)
}
}
\ No newline at end of file
package org.rosi_project.model_management.sync.helper
import org.rosi_project.model_management.sync.roles.IRoleManager
import org.rosi_project.model_management.core.PlayerSync
/**
* PART OF RSYNC-CORE by Christopher Werner (TUD)
* Helper class for all construction processes to manage standard work loads.
*/
class ConstructionContainer(val startElement: Boolean, val constructed: Boolean, val player: PlayerSync, val manager: IRoleManager) {
/**
* Returns true if it is the start construction element.
*/
def isStartElement(): Boolean = startElement
/**
* Return true if it is new constructed.
*/
def isConstructed(): Boolean = constructed
/**
* Get the PlayerSync instance of this element.
*/
def getPlayerInstance(): PlayerSync = player
/**
* Get the RoleManager instance of this element
*/
def getManagerInstance(): IRoleManager = manager
}
package org.rosi_project.model_management.sync.helper
import org.rosi_project.model_management.sync.roles.IRoleManager
import org.rosi_project.model_management.core.PlayerSync
/**
* PART OF RSYNC-CORE by Christopher Werner (TUD)
* Helper class for all integration processes to manage standard work loads.
*/
class IntegrationContainer (val newPlayerInstance: PlayerSync, val oldPlayerInstance: PlayerSync) {
var simpleRelatedManagerConnection: Boolean = true
var newManagerConnection: Boolean = true
var newManagerInstance: IRoleManager = null
/**
* Get the new PlayerSync instance of this element.
*/
def getNewPlayerInstance(): PlayerSync = newPlayerInstance
/**
* Get the new RoleManager instance of this element
*/
def getNewManagerInstance(): IRoleManager = newManagerInstance
/**
* Get the old PlayerSync instance of this element.
*/
def getOldPlayerInstance(): PlayerSync = oldPlayerInstance
}
\ No newline at end of file
package org.rosi_project.model_management.sync.lock
import java.sql.Timestamp
import java.util.Date
/**
* Represents a lock, which can be attached to an element.
*/
class ElementLock(protected val id: String, protected val creationDate: Long) {
/**
* returns the id of the lock
*/
def getId() : String = id
/**
* returns the creation-date of the lock
*/
def getCreationDate() : Long = creationDate
override def toString(): String = "ElementLock: [id:" + id + "] [creationDate: " + new Date(creationDate) + "]"
}
\ No newline at end of file
package org.rosi_project.model_management.sync.lock
import scala.collection.mutable.ListBuffer
import scala.collection.mutable.HashMap
import util.control.Breaks._
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.sql.Timestamp
import org.rosi_project.model_management.core.PlayerSync
import org.rosi_project.model_management.core.ModelElementLists
import org.rosi_project.model_management.util.UuidUtil
import scroll.internal.Compartment
import scala.collection.convert.ImplicitConversions.{`collection AsScalaIterable`, `map AsScalaConcurrentMap`}
import java.util.concurrent.atomic.AtomicInteger
import scala.sys.error
case class LockResult(success: Boolean, lock: ElementLock, wasDeleted: Boolean)
case class ElementListLockResult(lock: ElementLock, elements: ListBuffer[SynchronizationAware])
/**
* This singleton creates and removes locks. All lock-modifying methods are synchronizes for threadsafety.
* More informations about synchronized-methods: https://twitter.github.io/scala_school/concurrency.html
*/
object ElementLockProvider {
val logger = LoggerFactory.getLogger(ElementLockProvider.getClass)
/**
* The configurable locking-timeout.
*/
var TIMEOUT = 0
/**
* Checks if a lock is stale (is older then the locking-timeout).
*/
def lockIsStale(lock: ElementLock): Boolean = {
if (lock == null) {
return true
}
var lockTime: Long = lock.getCreationDate()
var isStale = (System.currentTimeMillis() - lockTime) > TIMEOUT
if (isStale) {
logger.info("Found stale lock with id: " + lock.getId())
}
return isStale
}
/**
* Generates a new ElementLock-Object.
*/
def provideLockObject(): ElementLock = new ElementLock(UuidUtil.generateUuid(), System.nanoTime())
/**
* Synchronized method for providing a new ElementLock on a element.
* returns -> lock-success, lock if lock-success, flag if element was deleted
*/
def provideLock(guid: String): LockResult = provideLockWithId(guid, UuidUtil.generateUuid())
/**
* Synchronized method for providing a new ElementLock with a specific id on a element.
* returns -> lock-success, lock if lock-success, flag if element was deleted
*/
def provideLockWithId(guid: String, id: String): LockResult = {
this.synchronized {
var player: SynchronizationAware = ModelElementLists.getElementByGuid(guid).asInstanceOf[SynchronizationAware]
if (player == null) {
return LockResult(success = false, null, wasDeleted = true)
}
val lock: ElementLock = new ElementLock(id, System.nanoTime())
var alreadyLocked: Boolean = false
player.getRelatedObjects().foreach { related =>
var p: SynchronizationAware = related.asInstanceOf[SynchronizationAware]
try {
if (p.lock != null && p.lock.getId() != id && !lockIsStale(p.lock)) {
alreadyLocked = true
}
} catch {
case e: NullPointerException => alreadyLocked = true
}
}
if (!alreadyLocked) {
player.getRelatedObjects().foreach { related =>
var p: SynchronizationAware = related.asInstanceOf[SynchronizationAware]
p.lock = lock
logger.info("Created new lock with id " + lock.getId() + " for element " + p.guid)
}
}
if (!alreadyLocked) {
return LockResult(success = true, lock, wasDeleted = false)
} else {
return LockResult(success = false, null, wasDeleted = false)
}
}
}
/**
* Synchronized method for providing a new ElementLock with a specific id on a list of elements in a specific model given by its key.
* returns -> lock if lock-success, locked elements if lock-success
*/
def provideLockWithIdForElementList(elements: Set[String], id: String): ElementListLockResult = {
this.synchronized {
var lock: ElementLock = new ElementLock(id, System.nanoTime())
var referencedElementsToBeLocked: ListBuffer[SynchronizationAware] = new ListBuffer[SynchronizationAware]()
elements.foreach { e =>
var lockElement: SynchronizationAware = ModelElementLists.getElementByGuid(e).asInstanceOf[SynchronizationAware]
if (lockElement != null) {
lockElement.getRelatedObjects().foreach { related =>
try {
if (related.asInstanceOf[SynchronizationAware].lock != null && related.asInstanceOf[SynchronizationAware].lock.getId() != id
&& !lockIsStale(related.asInstanceOf[SynchronizationAware].lock)) {
return ElementListLockResult(null, ListBuffer())
} else {
referencedElementsToBeLocked += related.asInstanceOf[SynchronizationAware]
}
} catch {
case e: NullPointerException => return ElementListLockResult(null, ListBuffer())
}
}
}
}
referencedElementsToBeLocked.foreach { elem =>
elem.lock = lock
}
return ElementListLockResult(lock, referencedElementsToBeLocked)
}
}
/**
* Synchronized method for providing a new ElementLock on a element and its references.
* returns -> lock-success, lock if lock-success, flag if referencing element was deleted
*/
def provideLockForElements(referencingElementGuid: String, referencingElementModel: String,
elements: Map[String, Set[String]], id: String): LockResult = {
return provideLockWithIdForElements(referencingElementGuid, referencingElementModel, elements, id)
}
/**
* Synchronized method for providing a new ElementLock with a specific id on a element and its references.
* returns -> lock-success, lock if lock-success, flag if referencing element was deleted
*/
def provideLockWithIdForElements(referencingElementGuid: String, referencingElementModel: String,
elements: Map[String, Set[String]], id: String): LockResult = {
this.synchronized {
var lock: ElementLock = new ElementLock(id, System.nanoTime())
var foundReferencingElement: Boolean = false
var referencedElementsToBeLocked: Set[SynchronizationAware] = Set[SynchronizationAware]()
// check referencing element
var referencingModelElement: SynchronizationAware = ModelElementLists.getElementByGuid(referencingElementGuid).asInstanceOf[SynchronizationAware]
if (referencingModelElement != null) {
referencingModelElement.getRelatedObjects().foreach { related =>
var p: SynchronizationAware = related.asInstanceOf[SynchronizationAware]
if (p.lock != null && p.lock.getId() != id && !lockIsStale(p.lock)) {
return LockResult(success = false, null, wasDeleted = false)
} else {
referencedElementsToBeLocked += p
}
}
foundReferencingElement = true
}
if (!foundReferencingElement) {
return LockResult(success = false, null, wasDeleted = true)
}
// check referenced elements
// iterate model-element-types of elements
for ((k, v) <- elements) {
// iterate elements in models
v.foreach { guid =>
val player: SynchronizationAware = ModelElementLists.getElementByGuid(referencingElementGuid).asInstanceOf[SynchronizationAware]
if (player != null) {
// we found a referenced element
player.getRelatedObjects().foreach { related =>
var p: SynchronizationAware = related.asInstanceOf[SynchronizationAware]
if (p.lock != null && p.lock.getId() != id && !lockIsStale(p.lock)) {
logger.info("wrong elem: " + p.guid)
return LockResult(success = false, null, wasDeleted = false)
} else {
referencedElementsToBeLocked += p
}
}
}
}
}
// lock referencing element and not deleted referenced elements
referencedElementsToBeLocked.foreach { elem =>
elem.lock = lock
}
return LockResult(success = true, lock, wasDeleted = false)
}
}
private def unlock(typedElement: SynchronizationAware, lockId: String): Unit ={
if (typedElement.lock != null && typedElement.lock.getId() == lockId) {
typedElement.lock = null
typedElement.getRelatedObjects().foreach { related =>
logger.info("Unlocking element: " + related.asInstanceOf[SynchronizationAware].guid)
related.asInstanceOf[SynchronizationAware].lock = null
}
}
}
/**
* Removes locks with a specific if id from all elements in models with given keys.
*/
def removeLocks(models: Set[String], lockId: String): Unit = {
this.synchronized {
models.foreach { m =>
val elements: Set[SynchronizationAware] = ModelElementLists.getDirectElementsFromType(m)
elements.foreach { e =>
val typedElement: SynchronizationAware = e.asInstanceOf[SynchronizationAware]
unlock(typedElement, lockId)
}
}
}
}
/**
* Removes locks with a specific if id from all elements in all models
*/
def removeLocksInAllModels(lockId: String): Unit = {
this.synchronized {
ModelElementLists.elements.forEach { (_, elements) =>
elements.values().foreach { element =>
val typedElement: SynchronizationAware = element.asInstanceOf[SynchronizationAware]
unlock(typedElement, lockId)
}
}
}
}
private def _removeLockFromElement(lockId: String, guid: String): Unit ={
val typedElement: SynchronizationAware = ModelElementLists.getElementByGuid(guid).asInstanceOf[SynchronizationAware]
if (typedElement != null && typedElement.lock != null && typedElement.lock.getId() == lockId && typedElement.guid == guid) {
unlock(typedElement, lockId)
}
}
/**
* Removes lock with a specific id from a element given by its guid.
*/
def removeLocksFromElement(lockId: String, guid: String): Unit = {
this.synchronized {
_removeLockFromElement(lockId, guid)
}
}
/**
* Removes a lock with a specific id from a set of elements given by their guid
*/
def removeLocksFromElements(lockId: String, guids: Set[String]): Unit = {
this.synchronized {
guids.foreach(guid => {
_removeLockFromElement(lockId, guid)
})
}
}
}
\ No newline at end of file
package org.rosi_project.model_management.sync.lock
import org.rosi_project.model_management.core.PlayerSync
/**
* Integrates locks, GUID's and owners into all elements of all models.
*/
abstract class SynchronizationAware(var lock: ElementLock, val guid: String, var owner: String) extends PlayerSync {
def getOwner(): String = owner
def setOwner(s: String): Unit ={
owner = s
}
def getLock(): ElementLock = lock
def setLock(lock: ElementLock): Unit ={
this.lock = lock
}
def getGuid(): String = guid
}
\ No newline at end of file
package org.rosi_project.model_management.sync.procedures
import org.rosi_project.model_management.{ServerChangeRecord, ServerReferenceChangeRecord}
import org.rosi_project.model_management.sync.procedures.data._
import org.rosi_project.model_management.sync.snapshot._
import org.rosi_project.model_management.sync.lock._
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
/**
* Base class for all synchronization-algorithms (phase of generating the SCR).
*/
trait BaseResponseGeneration {
/**
* Builds the SCR. Input date comes from the corresponding synchronization-service.
* cer -> from request
* idMapping -> maps global to local IDs for new elements
* notUpdatedOnServer -> IDs of elements where update was not applies & RV/TS is not higher
*/
def buildResponse(models: Set[String], idMapping: Map[String, String], cer: Seq[ClientEntireRecord], notUpdatedOnServer: Set[String], owner: String): mutable.Map[String, ListBuffer[ServerChangeRecord]]
/**
* Build the data-part of the SCR.
* snapshot -> has to be created in buildResponse (list of meta-informations about element at response-generation-time)
* idMapping -> maps global to local IDs for new elements
* notUpdatedOnServer -> IDs of elements where update was not applies & RV/TS is not higher
* records -> will be filled with datachanges
*/
def buildDataChanges(snapshot: ListBuffer[Snapshot], idMapping: Map[String, String], cer: Seq[ClientEntireRecord], notUpdatedOnServer: Set[String],
lock: ElementLock, records: mutable.Map[String, ListBuffer[ServerChangeRecord]], owner: String): Int
/**
* Build the data-part of the SCR.
* snapshot -> has to be created in buildResponse (list of meta-informations about element at response-generation-time)
* idMapping -> maps global to local IDs for new elements
* notUpdatedOnServer -> IDs of elements where update was not applies & RV/TS is not higher
* records -> filled with datachanges by buildDataChanges-method
* referenerecords -> will be filled with referencechanges
* processedReferencingElements -> already for reference-part of response processed elements with reference-changes
*/
def buildReferenceChanges(snapshot: ListBuffer[Snapshot], idMapping: Map[String, String], cer: Seq[ClientEntireRecord], notUpdatedOnServer: Set[String], lock: ElementLock,
records: mutable.Map[String, ListBuffer[ServerChangeRecord]], referenceRecords: ListBuffer[ServerReferenceChangeRecord],
processedReferencingElements: ListBuffer[String], owner: String): Int
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment