Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Valter's work addressing basho/riak_dt#99 #113

Open
wants to merge 34 commits into
base: 2.0
Choose a base branch
from

Conversation

russelldb
Copy link
Member

I've opened this pull request to keep track of comments/feedback as I work through the code.

russelldb and others added 22 commits December 8, 2014 14:38
Also takes care to not duplicate lots of clocks throughout structure.

Still uses dots at head of field to solve the bottom vs. bottomish thing
Added remove subtree

Missing:
- Control visibility of elements that have tombstones (recursive function, may be expensive)
- Add context to remove subtree
Corrected some wrong logic in clear tombstones.
Use it on propagate_remove() to fix error in test.
@russelldb russelldb self-assigned this Feb 3, 2015
balegas added 3 commits February 3, 2015 23:41
Removed unnecessary code
replaced raik_dt_vclock:fresh() by macro
Removed whitespaces
…_deferred/2 from the interface.

Fixed some issues with map dialyzer.
@balegas
Copy link

balegas commented Feb 9, 2015

The current version of the map clears deferred operations when an entry is removed (and no dot survives), allowing some dots that should be deleted by a deferred operation to remain in the state:

  • OpA removed "b -> 1" in replica A with the context of B;
  • A's context does not descend from B, deferring OpA;
  • OpA1 removes entry b, clears the entry and the deferred op in replica A;
  • A and B merge, "b -> 1" is added back to A and not cleared by OpA as intended because the deferred operation was cleared by OpA1

In a nutshell, i've changed the Map data-type to avoid losing these deferred operations.
I added some form of tombstone in the state that tells that an entry is removed, but keeps the value while it has deferred operations that are not covered by the object's clock.
Changes were made in the remove operation to fill this tombstone when an entry with deferred operations is deleted.
Merge() was modified to clear tombstones
Value() was changed to hide elements that are removed but the tombstone is not covered by the map clock yet.

The remove operation now calls a propagate_remove() function that recursively checks if any child of the current map entry has any deferred operations. All deferred operations are merged into the object clock and propagated to the root element that was deleted, filling the tombstone of the map entries on the way.
While an element has a tombstone, the entry and its subtree are kept (immediately remove dots that are covered by the clock). When the merge occurs and the deferred operations arrive, clear_tombstones() checks what entries can be deleted: if any child received a new dot, that entry is kept; If no new dot was added the entry can be deleted (also checks empty entry) --- the tombstone is only erased when covered by the map clock. To read the object, similar rules are applied: if an entry has a tombstone, check if any child has dots that are not covered by the tombstone to show/hide the entry.

Since the amount of meta-data in the object state was growing, i decided to separate the meta-data from the actual value so a map entry is now {{Dots, Seen, Tombstone},CRDT}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants