Fix concurrent modification exception

This commit is contained in:
J-Jamet
2022-01-19 19:12:44 +01:00
parent 0e21c75007
commit 223a8e9a5e
7 changed files with 47 additions and 28 deletions

View File

@@ -139,8 +139,9 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
dest.writeInt(binaryDataId ?: -1)
}
fun updateWith(source: EntryKDB) {
super.updateWith(source)
fun updateWith(source: EntryKDB,
updateParents: Boolean = true) {
super.updateWith(source, updateParents)
title = source.title
username = source.username
password = source.password

View File

@@ -110,8 +110,10 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
* Update with deep copy of each entry element
* @param source
*/
fun updateWith(source: EntryKDBX, copyHistory: Boolean = true) {
super.updateWith(source)
fun updateWith(source: EntryKDBX,
copyHistory: Boolean = true,
updateParents: Boolean = true) {
super.updateWith(source, updateParents)
usageCount = source.usageCount
locationChanged = DateInstant(source.locationChanged)
customData = CustomData(source.customData)

View File

@@ -53,8 +53,9 @@ class GroupKDB : GroupVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
dest.writeInt(groupFlags)
}
fun updateWith(source: GroupKDB) {
super.updateWith(source)
fun updateWith(source: GroupKDB,
updateParents: Boolean = true) {
super.updateWith(source, updateParents)
groupFlags = source.groupFlags
}

View File

@@ -102,8 +102,9 @@ class GroupKDBX : GroupVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
dest.writeParcelable(ParcelUuid(previousParentGroup), flags)
}
fun updateWith(source: GroupKDBX) {
super.updateWith(source)
fun updateWith(source: GroupKDBX,
updateParents: Boolean = true) {
super.updateWith(source, updateParents)
usageCount = source.usageCount
locationChanged = DateInstant(source.locationChanged)
// Add all custom elements in map

View File

@@ -51,12 +51,15 @@ abstract class GroupVersioned
dest.writeString(titleGroup)
}
protected fun updateWith(source: GroupVersioned<GroupId, EntryId, Group, Entry>) {
super.updateWith(source)
protected fun updateWith(source: GroupVersioned<GroupId, EntryId, Group, Entry>,
updateParents: Boolean = true) {
super.updateWith(source, updateParents)
titleGroup = source.titleGroup
removeChildren()
childGroups.addAll(source.childGroups)
childEntries.addAll(source.childEntries)
if (updateParents) {
removeChildren()
childGroups.addAll(source.childGroups)
childEntries.addAll(source.childEntries)
}
}
override var title: String

View File

@@ -68,9 +68,12 @@ abstract class NodeVersioned<IdType, Parent : GroupVersionedInterface<Parent, En
return 0
}
protected fun updateWith(source: NodeVersioned<IdType, Parent, Entry>) {
protected fun updateWith(source: NodeVersioned<IdType, Parent, Entry>,
updateParents: Boolean = true) {
this.nodeId = copyNodeId(source.nodeId)
this.parent = source.parent
if (updateParents) {
this.parent = source.parent
}
this.icon = source.icon
this.creationTime = DateInstant(source.creationTime)
this.lastModificationTime = DateInstant(source.lastModificationTime)

View File

@@ -80,7 +80,8 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
database.settingsChanged = databaseToMerge.settingsChanged
}
val rootGroupId = database.rootGroup?.nodeId
val rootGroup = database.rootGroup
val rootGroupId = rootGroup?.nodeId
val rootGroupToMerge = databaseToMerge.rootGroup
val rootGroupIdToMerge = rootGroupToMerge?.nodeId
@@ -91,16 +92,18 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
// UUID of the root group to merge is unknown
if (database.getGroupById(rootGroupIdToMerge) == null) {
// Change it to copy children database root
// TODO Test merge root
databaseToMerge.removeGroupIndex(rootGroupToMerge)
rootGroupToMerge.nodeId = rootGroupId
databaseToMerge.addGroupIndex(rootGroupToMerge)
}
// Merge root group
mergeGroup(rootGroupToMerge, databaseToMerge)
if (rootGroup.lastModificationTime.date
.before(rootGroupToMerge.lastModificationTime.date)) {
rootGroup.updateWith(rootGroupToMerge, updateParents = false)
}
// Merge children
databaseToMerge.rootGroup?.doForEachChild(
rootGroupToMerge.doForEachChild(
object : NodeHandler<EntryKDBX>() {
override fun operate(node: EntryKDBX): Boolean {
mergeEntry(node, databaseToMerge)
@@ -206,16 +209,19 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
private fun mergeEntry(nodeToMerge: EntryKDBX, databaseToMerge: DatabaseKDBX) {
val entryId = nodeToMerge.nodeId
val entryToMerge = databaseToMerge.getEntryById(entryId)
val entry = database.getEntryById(entryId)
val deletedObject = database.getDeletedObject(entryId)
if (entryToMerge != null) {
databaseToMerge.getEntryById(entryId)?.let { srcEntryToMerge ->
// Retrieve parent in current database
var parentEntryToMerge: GroupKDBX? = null
entryToMerge.parent?.nodeId?.let {
srcEntryToMerge.parent?.nodeId?.let {
parentEntryToMerge = database.getGroupById(it)
}
val entryToMerge = EntryKDBX().apply {
updateWith(srcEntryToMerge, copyHistory = true, updateParents = false)
}
// Copy attachments in main pool
val newAttachments = mutableListOf<Attachment>()
entryToMerge.getAttachments(databaseToMerge.attachmentPool).forEach { attachment ->
@@ -257,7 +263,7 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
) {
addHistory(entry, entryToMerge)
if (parentEntryToMerge == entry.parent) {
entry.updateWith(entryToMerge)
entry.updateWith(entryToMerge, copyHistory = true, updateParents = false)
} else {
// Update entry with databaseEntryToMerge and merge history
database.removeEntryFrom(entry, entry.parent)
@@ -289,7 +295,7 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
it.lastModificationTime == entryA.lastModificationTime
} == null) {
val history = EntryKDBX().apply {
updateWith(entryA, false)
updateWith(entryA, copyHistory = false, updateParents = false)
parent = null
}
entryB.addEntryToHistory(history)
@@ -298,16 +304,18 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
private fun mergeGroup(nodeToMerge: GroupKDBX, databaseToMerge: DatabaseKDBX) {
val groupId = nodeToMerge.nodeId
val groupToMerge = databaseToMerge.getGroupById(groupId)
val group = database.getGroupById(groupId)
val deletedObject = database.getDeletedObject(groupId)
if (groupToMerge != null) {
databaseToMerge.getGroupById(groupId)?.let { srcGroupToMerge ->
// Retrieve parent in current database
var parentGroupToMerge: GroupKDBX? = null
groupToMerge.parent?.nodeId?.let {
srcGroupToMerge.parent?.nodeId?.let {
parentGroupToMerge = database.getGroupById(it)
}
val groupToMerge = GroupKDBX().apply {
updateWith(srcGroupToMerge, updateParents = false)
}
if (group == null) {
// If group parent to add exists and in current database
@@ -325,7 +333,7 @@ class DatabaseKDBXMerger(private var database: DatabaseKDBX) {
.before(groupToMerge.lastModificationTime.date)
) {
if (parentGroupToMerge == group.parent) {
group.updateWith(groupToMerge)
group.updateWith(groupToMerge, false)
} else {
database.removeGroupFrom(group, group.parent)
if (parentGroupToMerge != null) {