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

fix for dict update same key after delete it #119

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jasonjoo2010
Copy link
Contributor

following calls will be fail:

dict_set(map, "test", "demo");
dict_delete(map, "test");
dict_set(map, "test", "new value"); //will not set it

this pr is submitted to fix it

@tevino tevino requested a review from maralla March 23, 2017 12:14
@doyoubi
Copy link
Contributor

doyoubi commented Mar 24, 2017

Thanks for reporting this issue. The current design of dict is not for manipulating the key dynamically. It does provide dict_delete though, it's never used. In fact, we can't even set an existing key again to change its value, because it would require checking the existence of the key by comparing key string and we just don't need it currently.
Any different ideas? @maralla

@doyoubi
Copy link
Contributor

doyoubi commented Mar 30, 2017

I think we have 2 choices here:

  1. In dict_index, keep scanning the table when there is hash collision. Then support deletion and modification of existing keys.
  2. Completely disable dynamic modification of existing keys

In fact the existing codes don't rely on the changing of existing keys. Are you building something requires it? @jasonjoo2010

@jasonjoo2010
Copy link
Contributor Author

@doyoubi
yelp, i took corvus as a training project several days ago and found the problem.

considering modification, would it never be used to be a full functional dict in future? e.g. delete or update(index -> delete -> set)

Solution 1 maybe has a poor performance
Solution 2 we should mark it as a half functional dict

the commit currently would just reuse some slot deleted before through adding a simple condition when conflicted

@doyoubi
Copy link
Contributor

doyoubi commented Mar 30, 2017

Or we just support deletion and modification but leave the dict_index unchanged. And we should add some docs on it, especially for the case that we can't set the keys with same hash (as the current dict_index can't work in this case).

@tevino
Copy link
Contributor

tevino commented Mar 30, 2017

Documenting the half functional dict sounds good.

@jasonjoo2010
Copy link
Contributor Author

The only special things now is that we should DELETE first when the key already exists in the dict.

So we can document THIS for special.

Or we can add this logic inside dict_set if we feel better.

Wouldn't modification be needed in future?

@maralla
Copy link
Contributor

maralla commented Mar 30, 2017

Current dict implementation is very limited. I think we should have a refactor to make it fully functional.

@maralla
Copy link
Contributor

maralla commented Mar 30, 2017

It's much simple than I thought to make it support setting the same key multiple times:

     while (1) {
         struct bucket *bucket = &dict->buckets[pos];
 
+        // Empty, set bucket
         if (!bucket->setted) {
             set_bucket(bucket, hash, key, data);
             return;
         }
 
         probe_dist = PSL(dict->capacity, bucket->hash, pos);
+
+        // Same key, update the bucket
+        if (probe_dist == dist && strcmp(key, bucket->key) == 0) {
+            set_bucket(bucket, hash, key, data);
+            return;
+        }
+
         if (probe_dist < dist) {
             if (bucket->deleted) {
                 set_bucket(bucket, hash, key, data);

The code is not fully tested.

@jasonjoo2010
Copy link
Contributor Author

@maralla

I do have considered this kind of fix.

But there maybe a memory management problem if we just update the pointer to a new one simply. Caller could FREE the pointer if necessarily when we force him to do existence checking when updating.

@maralla
Copy link
Contributor

maralla commented Mar 30, 2017

I think the memory problem is up to the caller. If the value is dynamically allocated, dict_index should be called before set the key.

@jasonjoo2010
Copy link
Contributor Author

@maralla

yes, you are right. it does the responsibility of caller.

btw, maybe the small fix from our training project cost us too much discussion.
we can make some conclusions quickly, i think.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

6 participants