fun refactorAddMissedLinks()

in entity-store/src/main/kotlin/jetbrains/exodus/entitystore/PersistentEntityStoreRefactorings.kt [288:439]


    fun refactorAddMissedLinks() {
        store.executeInReadonlyTransaction { txn ->
            txn as PersistentStoreTransaction
            for (entityType in store.getEntityTypes(txn)) {
                logInfo("Refactoring restoring missed links in [$entityType]")
                runReadonlyTransactionSafeForEntityType(entityType) {

                    val missedLinks = ArrayList<Pair<ByteIterable, ByteIterable>>()
                    val entityTypeId = store.getEntityTypeId(txn, entityType, false)
                    val linksTable = store.getLinksTable(txn, entityTypeId)
                    val envTxn = txn.environmentTransaction
                    val missedLinkTypes = IntHashSet()

                    linksTable.getFirstIndexCursor(envTxn).use { cursor ->
                        while (cursor.next) {
                            val first = cursor.key
                            val second = cursor.value
                            var linkValue: LinkValue? = null

                            try {
                                linkValue = LinkValue.entryToLinkValue(second)
                            } catch (ignore: Exception) {
                            }

                            if (linkValue != null) {
                                if (!linksTable.contains2(envTxn, first, second)) {
                                    var propertyKey: PropertyKey? = null
                                    try {
                                        propertyKey = PropertyKey.entryToPropertyKey(first)
                                    } catch (ignore: Exception) {
                                    }

                                    try {
                                        txn.getEntity(linkValue.entityId)
                                    } catch (e: Exception) {
                                        linkValue = null
                                    }

                                    if (linkValue != null) {
                                        try {
                                            store.getEntityType(txn, linkValue.entityId.typeId)
                                        } catch (e: Exception) {
                                            linkValue = null
                                        }
                                    }

                                    if (propertyKey != null && linkValue != null) {
                                        val targetEntityId = linkValue.entityId

                                        missedLinkTypes.add(targetEntityId.typeId)
                                        missedLinks.add(ArrayByteIterable(first) to ArrayByteIterable(second))
                                    }
                                }
                            }
                        }
                    }

                    if (missedLinks.isNotEmpty()) {
                        store.environment.executeInExclusiveTransaction { txn ->
                            for (missedLink in missedLinks) {
                                val propertyKey = PropertyKey.entryToPropertyKey(missedLink.first)

                                linksTable.put(
                                    txn, propertyKey.entityLocalId, missedLink.second, true,
                                    propertyKey.propertyId
                                )
                            }
                        }

                        val redundantLinkTypeNames = HashSet<String>(missedLinkTypes.size)
                        for (typeId in missedLinkTypes) {
                            redundantLinkTypeNames.add(store.getEntityType(txn, typeId))
                        }

                        logInfo(
                            missedLinks.size.toString() + " links missing in second  " +
                                    "table found for [" + entityType + " ] and targets: $redundantLinkTypeNames and fixed"
                        )

                        missedLinks.clear()
                        missedLinkTypes.clear()
                    }

                    linksTable.getSecondIndexCursor(envTxn).use { cursor ->
                        while (cursor.next) {
                            val second = cursor.key
                            val first = cursor.value

                            var linkValue: LinkValue? = null
                            try {
                                linkValue = LinkValue.entryToLinkValue(second)
                            } catch (ignore: Exception) {
                            }

                            if (linkValue != null) {
                                if (!linksTable.contains(envTxn, first, second)) {
                                    var propertyKey: PropertyKey? = null
                                    try {
                                        propertyKey = PropertyKey.entryToPropertyKey(first)
                                    } catch (ignore: Exception) {
                                    }

                                    try {
                                        txn.getEntity(linkValue!!.entityId)
                                    } catch (e: Exception) {
                                        linkValue = null
                                    }

                                    if (linkValue != null) {
                                        try {
                                            store.getEntityType(txn, linkValue!!.entityId.typeId)
                                        } catch (e: Exception) {
                                            linkValue = null
                                        }
                                    }

                                    if (propertyKey != null && linkValue != null) {
                                        val targetEntityId = linkValue!!.entityId
                                        missedLinks.add(ArrayByteIterable(first) to ArrayByteIterable(second))
                                        missedLinkTypes.add(targetEntityId.typeId)
                                    }
                                }
                            }
                        }
                    }

                    if (missedLinks.isNotEmpty()) {
                        store.environment.executeInExclusiveTransaction { txn ->
                            for (missedLink in missedLinks) {
                                val propertyKey = PropertyKey.entryToPropertyKey(missedLink.first)

                                linksTable.put(
                                    txn, propertyKey.entityLocalId, missedLink.second, true,
                                    propertyKey.propertyId
                                )
                            }
                        }

                        val redundantLinkTypeNames = HashSet<String>(missedLinkTypes.size)
                        for (typeId in missedLinkTypes) {
                            redundantLinkTypeNames.add(store.getEntityType(txn, typeId))
                        }

                        logInfo(
                            "${missedLinks.size} links missing in first table found for [$entityType] " +
                                    "and targets: $redundantLinkTypeNames and fixed"
                        )
                    }
                }
            }
        }
    }