-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
add experimental daemon plugin for 9P2000.L support #6612
Conversation
678a532
to
50c30a4
Compare
@@ -0,0 +1,168 @@ | |||
package p9client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for testing, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is intended to become a wrapper library for clients to use. So that they can dial our plugin's server easily. Longer term it should shape the VFS interface. Currently we just use 9P semantics, but we can define operations such as Readdir
here to be more brief, much like how MFS does with operations like Mkdir
.
e.g.
doing ents, err := client.Readdir(someFilesystem, "/some/path")
rather than using the interface directly yourself.
However this is more related to ipfs-inactive/package-managers#71 and should be broken up. This PR should only relate to the server portion at the moment so I'll remove this from the patchset.
|
||
cfg := &Config{} | ||
if env.Config != nil { | ||
byteRep, err := json.Marshal(env.Config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Maybe we should pass in a json.RawMessage
? Or does that leak too much?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying env.Config
would change to be of type json.RawMessage
rather than interface{}?[]byte
That probably makes the most sense. I'm trying to think of a situation where you'd need raw bytes in the plugin config, that can't be fit inside formatted json, but nothing comes to immediate mind that wouldn't be better stored elsewhere.
(e.g. storing a CID to some binary in the config rather than encoding the (complete) binary itself)
So long as we discard the object once we've loaded and parsed, I'd imagine things wouldn't use any more resources than the current implementation. But I'm saying that without having doing any actual comparisons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, I'm assuming you could have meant casting asserting env.Config to as a RawMessage as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went forward with the second one for now
b6d1506
but this isn't tested yet.
This #6612 (comment) likely needs to be resolved, and I'd like to see some method for Plugins to initiate a Save()/Store()/Whatever()
for their section (only) of the config, from within go
, if we possibly can.
e.g., I'd like to be able to load plugin config, modify some structure, and push it back to the config, but not have full config access.
var err error | ||
for _, name := range names { | ||
//TODO: timerctx; don't want to hang forever | ||
if walkedNode.Path, err = id.core.ResolvePath(id.Ctx, corepath.Join(walkedNode.Path, name)); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. This looks like something we might want to tweak in the CoreAPI. We probably want a version that returns a channel of Resolved{Component: string, To: Path}
results.
TODO later: ipfs/interface-go-ipfs-core#42
//defer asyncContext.Cancel() | ||
defer close(relayChan) | ||
|
||
for i := 0; i != oStat.NumLinks; i++ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't work with sharded directories.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just wait for Ls
to close coreChan
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed how IPFS Readdir logic works, so that the system checks and stores the coreChan on Open(), and progresses on it during Readdir(), in a forward-only fashion.
https://github.com/ipfs/go-ipfs/blob/059c218a76149c270f6cd11d21a4a9dbd9172bae/plugin/plugins/filesystem/nodes/ipfs.go#L103
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ needs test: create sharded directory and read from it
Main things to address now:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A friendly reminder from someone trying to extract perf information out of ipfs to understand how gateways are performing, please pass contexts around everywhere before this gets merged. 😸
24c4aca
to
b9a988f
Compare
(Fixed building for |
2b9a5c2
to
d922b96
Compare
I apologize to anyone monitoring this thread for using all of their RAM. There's a lot of comments in here! Judgment needed on unresolved issues (ping @Stebalien) @ myself
Do another pass on permissions Discuss how to handle overridding the config file's Multiaddr string / Environment variables We've neglected to properly handle configuration in general, put thought into it and write a variety of tests
Reassess how/why we use loggers the way we do, and document it regardless: Make a pass on QID's in general: Read doesn't loop until full: |
We'll also want to make sure this change gets bubbled up for our Windows users: multiformats/go-multiaddr-net#60 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General advice:
- Be careful about premature optimizations (or generalizations). The walking code is getting pretty complicated.
- There are quite a few commented code chunks. When commenting out (then committing) code like this, explaining why it's commented helps.
Other than that, this looks like it's getting close.
// store error on the fs object then close our syncing channel (see use in `Close` below) | ||
fs.serverErr = server.Serve(manet.NetListener(fs.listener)) | ||
|
||
if fs.closing { //[async] we expect `Accept` to fail while `Close` is in progress |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 (nice comment)
// Storage for file's metadata | ||
Qid *p9.QID | ||
meta *p9.Attr | ||
metaMask *p9.AttrMask |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this offline. Just storing the data probably isn't an issue.
This will cause issues when moving back and forth though (walking back to ..), so we should probably store metadata in an index on the FS instead.
Define "cause issues"? If this breaks ..
, we should definitely just pass these by value and optimize later.
Qid *p9.QID | ||
meta *p9.Attr | ||
metaMask *p9.AttrMask | ||
Logger logging.EventLogger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
|
||
It is valid to return a newly constructed reference or modify and return the existing reference | ||
as long as `QID` is ready to be called on the resulting node | ||
and resources are reaped where sensible within the fs implementation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs to clarify who owns what. The interface contract needs to specify constraints on the inputs/outputs, describing what may/may not happen internally isn't all that important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like "Step
steps into the current directory, consuming the WalkRef
. After calling Step, the original WalkRef must not be used."
select { | ||
case entry, open := <-id.directory.entryChan: | ||
if !open { | ||
//id.operationsCancel() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uncomment or document?
} | ||
|
||
// OverlayFileMeta holds data relevant to file system nodes themselves | ||
type OverlayFileMeta struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems reasonable but I'd definitely include that reasoning in the code docs.
|
||
/* general helpers */ | ||
|
||
func (b *Base) ninePath() p9Path { return b.qid.Path } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This really doesn't need to exist.
Part of: ipfs-inactive/package-managers#74
Draft TODO:
go test
)fsx
, etc.)go-ipfs/plugin
should support plugin scoped configs (we can punt on this)go-ipfs-config
dependency in our plugin, and instead, receive some context fromgo-ipfs/plugin
var cfg Config.FileSystem = findCfgPathAndLoad(myNonStandardPath, &myWhateverFormat, ...
could be avoided by changingPlugin.Init()
to something likePlugin.Init(context, opts...)
Trying to enable the experiment throughipfs config --json Experimental.FileSystemEnabled true
should workexperimental-features.md
🠗Other known issues:
go.mod
has replace directives for this patchset, these need to point to the final dependency commits before mergingDirectory reads in particular need to be fixed before merging. (currently reads entire directory every request and returns requested slice instead of using a forward-only stream)