Skip to content

Commit

Permalink
Update getRootThreadSafe() to return a deep-copied JsonObject (#176)
Browse files Browse the repository at this point in the history
* update consumer-rules.pro

* add getRootThreadSafe()
  • Loading branch information
7hong13 authored May 13, 2024
1 parent 237740c commit 57e3d89
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 27 deletions.
36 changes: 18 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
cache: 'gradle'
- run: chmod +x gradlew
- uses: gradle/gradle-build-action@v2
- uses: gradle/actions/setup-gradle@v3
- run: ./gradlew lintKotlin
- run: ./gradlew lint

Expand All @@ -28,17 +28,17 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
cache: 'gradle'
- run: chmod +x gradlew
- uses: gradle/gradle-build-action@v2
- uses: gradle/actions/setup-gradle@v3
- run: ./gradlew yorkie:testDebugUnitTest
- run: ./gradlew yorkie:jacocoDebugTestReport
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: unit-test-artifact
path: yorkie/build/reports/jacoco/jacocoDebugTestReport/jacocoDebugTestReport.xml
Expand All @@ -53,18 +53,18 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
cache: 'gradle'
- run: chmod +x gradlew
- uses: gradle/gradle-build-action@v2
- uses: gradle/actions/setup-gradle@v3
- run: |
docker system prune --all --force
docker-compose -f docker/docker-compose-ci.yml up --build -d
- uses: actions/cache@v3
- uses: actions/cache@v4
id: avd-cache
with:
path: |
Expand Down Expand Up @@ -101,7 +101,7 @@ jobs:
- if: ${{ matrix.api-level == 24 }}
run: ./gradlew yorkie:jacocoDebugTestReport
- if: ${{ matrix.api-level == 24 }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: android-test-artifact
path: yorkie/build/reports/jacoco/jacocoDebugTestReport/jacocoDebugTestReport.xml
Expand All @@ -112,7 +112,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@v2
- uses: codecov/codecov-action@v3
with:
Expand All @@ -126,15 +126,15 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
cache: 'gradle'
- run: chmod +x gradlew
- uses: gradle/gradle-build-action@v2
- uses: actions/cache@v3
- uses: gradle/actions/setup-gradle@v3
- uses: actions/cache@v4
id: avd-cache
with:
path: |
Expand Down Expand Up @@ -169,7 +169,7 @@ jobs:
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull
- run: |
echo "$(cat dev.yorkie.microbenchmark.test-benchmarkData.json)"
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: microbenchmark-artifact
path: dev.yorkie.microbenchmark.test-benchmarkData.json
3 changes: 3 additions & 0 deletions yorkie/consumer-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-keepclassmembernames class dev.yorkie.api.**.* {
*;
}
21 changes: 17 additions & 4 deletions yorkie/src/main/kotlin/dev/yorkie/document/Document.kt
Original file line number Diff line number Diff line change
Expand Up @@ -420,12 +420,25 @@ public class Document(
// TODO: also apply to root
}

/**
* Returns a new proxy of cloned root.
*/
public suspend fun getRoot(): JsonObject = withContext(dispatcher) {
val clone = ensureClone()
val context = ChangeContext(changeID.next(), clone.root)
JsonObject(context, clone.root.rootObject)
}

/**
* Returns a new proxy of deep-copied root.
* It ensures thread-safety by avoiding reuse of [clone].
*/
public suspend fun getRootThreadSafe(): JsonObject = withContext(dispatcher) {
val clone = ensureClone().deepCopy()
val context = ChangeContext(changeID.next(), clone.root)
JsonObject(context, clone.root.rootObject)
}

/**
* Deletes elements that were removed before the given time.
*/
Expand Down Expand Up @@ -554,8 +567,8 @@ public class Document(
public val disableGC: Boolean = false,
)

internal data class RootClone(
val root: CrdtRoot,
val presences: Presences,
)
internal data class RootClone(val root: CrdtRoot, val presences: Presences) {

fun deepCopy() = copy(root = root.deepCopy(), presences = presences.asPresences())
}
}
7 changes: 5 additions & 2 deletions yorkie/src/main/kotlin/dev/yorkie/document/crdt/CrdtTree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public typealias TreePosRange = Pair<CrdtTreePos, CrdtTreePos>

internal typealias CrdtTreeToken = TreeToken<CrdtTreeNode>

internal class CrdtTree(
internal data class CrdtTree(
val root: CrdtTreeNode,
override val createdAt: TimeTicket,
override var _movedAt: TimeTicket? = null,
Expand Down Expand Up @@ -556,7 +556,7 @@ internal class CrdtTree(
* Copies itself deeply.
*/
override fun deepCopy(): CrdtElement {
return CrdtTree(root.deepCopy(), createdAt, movedAt, removedAt)
return copy(root = root.deepCopy())
}

/**
Expand Down Expand Up @@ -847,6 +847,9 @@ internal data class CrdtTreeNode private constructor(
}
it.insPrevID = insPrevID
it.insNextID = insNextID
if (it.isText) {
it.value = value
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions yorkie/src/main/kotlin/dev/yorkie/document/crdt/Rht.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal class Rht : Collection<Rht.Node> {

val nodeKeyValueMap: Map<String, String>
get() {
return nodeMapByKey.entries.associate { (key, node) ->
return nodeMapByKey.filterValues { !it.isRemoved }.entries.associate { (key, node) ->
key to node.value
}
}
Expand All @@ -23,13 +23,14 @@ internal class Rht : Collection<Rht.Node> {
key: String,
value: String,
executedAt: TimeTicket,
isRemoved: Boolean = false,
) {
val prev = nodeMapByKey[key]
if (prev?.executedAt < executedAt) {
if (prev?.isRemoved == false) {
numberOfRemovedElements--
}
val node = Node(key, value, executedAt, false)
val node = Node(key, value, executedAt, isRemoved)
nodeMapByKey[key] = node
}
}
Expand Down Expand Up @@ -66,7 +67,7 @@ internal class Rht : Collection<Rht.Node> {
val rht = Rht()
nodeMapByKey.forEach {
val node = it.value
rht.set(node.key, node.value, node.executedAt)
rht.set(node.key, node.value, node.executedAt, node.isRemoved)
}
return rht
}
Expand Down

0 comments on commit 57e3d89

Please sign in to comment.