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

[WIP] Make the Node methods on ProtoNode thread-safe #4784

Closed
wants to merge 3 commits into from
Closed

[WIP] Make the Node methods on ProtoNode thread-safe #4784

wants to merge 3 commits into from

Conversation

schomatis
Copy link
Contributor

@schomatis schomatis commented Mar 7, 2018

This is a work in progress, not ready to be merged.

Test of thread-safety of the ProtoNode implementation of the Node interface (#3991). The Stat() method does an in-place sort that can result in an unordered link slice (giving an unexpected hash/CID).

Closes #3991.

@Kubuxu Kubuxu added the status/WIP This a Work In Progress label Mar 7, 2018
@schomatis schomatis requested a review from Kubuxu as a code owner March 22, 2018 20:31
@schomatis
Copy link
Contributor Author

@Stebalien Could you take a quick look at the last commit? It's still a WIP but just to check if I'm going in the right direction. The idea is to encapsulate the access to the node's cache, that way adding the Once lock should be pretty straight forward.

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a step in the right direction but I can't really review much until I see the final code.

// different parts of the system. As cid is the hash of the encoded
// they are closely tied together and this code should reflect that.
// If encoded is modified the cid is invalid (and should be set to nil).
cachedCID *cid.Cid
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, you can do this by creating an embedded struct:

type ProtoNode struct {
    // ...
    cached struct {
        once sync.Once
        cid *cid.Cid
        bytes []byte
    }
}

@@ -131,7 +133,7 @@ func (n *ProtoNode) AddRawLink(name string, l *ipld.Link) error {

// RemoveNodeLink removes a link on this node by the given name.
func (n *ProtoNode) RemoveNodeLink(name string) error {
n.encoded = nil
n.invalidateEncoding()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we're not invalidating the "encoding", just the "encoded" or cached object (I'd call it invalidateCache.

Encapsulated encoding access through `setEncoding` function.

Make `Marshal` function private (`marshal`) to follow the
`unmarshal` (private) - `DecodeProtobuf` (public) pattern.

Remove CID update from `EncodeProtobuf` function,
now it's only updated in its getter `Cid`.

License: MIT
Signed-off-by: Lucas Molas <schomatis@gmail.com>
The only time EncodeProtobuf was being called with force=true was in the
DagModifier functions, which are now modified to copy the node (invalidating
its cache) before modifying it (so the call to EncodeProtobuf will always
rework the encoded cache value).

License: MIT
Signed-off-by: Lucas Molas <schomatis@gmail.com>
License: MIT
Signed-off-by: Lucas Molas <schomatis@gmail.com>
@schomatis
Copy link
Contributor Author

@Stebalien Thanks for the previous review, it made much sense to encapsulate all the cache in a single structure.

I'm trying to add the Once lock inside EncodeProtobuf (see last commit) to control the access to the cached data (now that Marshal has been made privateEncodeProtobuf should be the single point of entry).

In case there is an error during the marshaling inside EncodeProtobuf, how should that case be handled? Right now I'm caching also the error, following the proposed API that once a node is committed it's frozen and can't be modified any more (the node should be copied to modify the new copy, not the old original). This means that if the node was improperly created and its marshaling fails (e.g., a corrupt node) the node should stay in that failed state, and another copy would be necessary to fix it. WDYT?

@schomatis
Copy link
Contributor Author

Closing as most of the code has been moved elsewhere, there may still be value here to inspire a similar PR in go-merkledag.

@schomatis schomatis closed this Dec 13, 2018
@schomatis schomatis deleted the fix/dag/protonode-thread-safe branch December 13, 2018 23:41
@schomatis schomatis restored the fix/dag/protonode-thread-safe branch December 13, 2018 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/WIP This a Work In Progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants