-
-
Notifications
You must be signed in to change notification settings - Fork 885
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
Feature/get local interfaces #1350
Conversation
(According to checkstyle configuration)
…es, too To keep the API stable, getNetworkIFs behavior is unchanged.
It seems like the tests are quite system-dependent. Here are the current failures from AppVeyor:
On my Linux development machine, I get a test failure because |
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.
Thanks for the PR! It looks great. A few changes I'd like:
- I'm not really happy with the term "inet" used in the javadocs. I'd prefer a more verbose term to represent the "not loopback or virtual" nature.
- Rather than a getX() and getAllX() pair, let's overload the methods. The new method will add a boolean argument, the old method will keep the no-arg version. In the Abstract object you can implement the no-arg delegating to the arg version with
false
. Then in the platform-specific code you only need to implement one method, with a boolean argument you can switch on.
@@ -77,13 +77,22 @@ | |||
List<HWDiskStore> getDiskStores(); | |||
|
|||
/** | |||
* Gets a list of {@link NetworkIF} objects, representing a network interface | |||
* Gets a list of inet {@link NetworkIF} objects, representing a network interface |
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'd prefer not to add inet
here as it's not clearly defined, and the object returned is part of the OSHI API.
I see throughout the changes you've used this term, though, so perhaps you need to just clearly define what "inet" means. Or use a more verbose term that's more clear.
* @return An {@code UnmodifiableList} of {@link NetworkIF} objects representing | ||
* the interfaces | ||
*/ | ||
List<NetworkIF> getAllNetworkIFs(); |
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.
Instead of a new name, let's just overload the original one. Make this second method getNetworkIFs(boolean includeLoopbackAndVirtual);
(or another shorter name that means the same). Calling the first method will simply redirect to getNetworkIFs(false)
and then you only have to really write the implementations for one method.
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 did not overload the method on purpose, following "Clean Code"'s statement about boolean parameters: https://medium.com/@amlcurran/clean-code-the-curse-of-a-boolean-parameter-c237a830b7a3
If you want, I can change it, though.
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.
Thanks for that article link. I did spend some time reading it and considering this issue, and present the following counter for discussion.
While the article makes great points, it's dealing primarily with mutually exclusive control flows. That, however, is not the case here. We are using overlapping/nearly-identical flows (iterating interfaces), with the only difference being a filtering parameter. We are not making the code any more complex than it already is; the existing code includes this conditional:
if (!netint.isLoopback() && netint.getHardwareAddress() != null) { .... }
All you'd do is add the boolean parameter (or its opposite) to that conditional.
Another consideration is API consistency. We use exactly the pattern I'm proposing in iterating Filesystems (see FileSystem.getFileStores(boolean localOnly)
). Of course, that's now complicated by the fact that there's a request to not filter the overlay filesystem types ( #1339 ), so perhaps a boolean is a poor choice there, or we may need a second parameter (probably a collection of strings). Also, the OperatingSystem
class has a default getProcesses()
which gets all processes, delegating to getProcesses(int limit, ProcessSort sort)
for the filtering/sorting/size limiting output. I see this as a very similar type of application.
More importantly, the API is designed to transparently work with the Jackson project's ObjectMapper
(see the Json
class in the oshi-demo
project). By default, this class automatically, via reflection, assumes a get*()
method maps directly to a field. Perhaps using get*()
is a bad choice to begin with, but at this point we're stuck with the API. Having two no-arg get*()
methods will duplicate the JSON output. The mapper does ignore the "getters" with arguments, and would ignore a method name that doesn't look like a getter (which is the reason queryNetworkInterfaces()
is not getNetworkInterfaces()
.)
So I'm not overly opposed to you using two separate methods if you make the "full method" a query*()
one, and then filter from those results in the get*()
method. That'd be an implementation detail. However, given the similarity to the existing API implementations, I'd prefer to just have a boolean filter parameter on whether to include the loopback interfaces.
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.
Also, complicating things, in the existing method there are two filters, the loopback and the virtual (whether a hardware address exists). So perhaps boolean isn't the best filtering, but open to ideas on how to make this both flexible and not overly complex (I don't want two booleans). I do think an "unfiltered" output vs. a "most common filters" with a boolean switch is a good compromise.
LOG.error("Socket exception when retrieving interfaces: {}", ex.getMessage()); | ||
} | ||
|
||
return new ArrayList<>(); |
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.
Use Collections.emptyList()
here.
SystemInfo si = new SystemInfo(); | ||
|
||
for (NetworkIF net : si.getHardware().getNetworkIFs()) { | ||
for (NetworkIF net : si.getHardware().getAllNetworkIFs()) { |
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.
Given one list is the superset of the other, it seems like we don't need to repeat all the tests, just do the "all" version for the detail and do at least one test for the "non-local/virtual" version to show the result isn't loopback, etc.
Interesting that appveyor fails now but didn't before. (It just passed tests on the master branch.) Even more interesting is that the failure, The linux failure seems like it should be excluded in that condition, can you submit a separate issue or PR for that? |
FYI, the macos failures may be a separate bug that I'm hunting down in the tcpstats structure. You can ignore them. |
I refactored the getNetworks() method. I tried to keep the API stable, though. |
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.
Looks good and works. I have two more requests and this will be ready to merge!
- DRY: just implement the no-arg to "false" delegation once in the AbstractHAL, and save yourself 10 other method calls.
- Move the boolean test outside of the loop (only test once) and move the exception handling to where it's thrown. This is logically the same as what you had, but lets us simplify the method.
oshi-core/src/main/java/oshi/hardware/common/AbstractNetworkIF.java
Outdated
Show resolved
Hide resolved
oshi-core/src/main/java/oshi/hardware/platform/linux/LinuxHardwareAbstractionLayer.java
Outdated
Show resolved
Hide resolved
Looks good with the latest commit! I'll do some final cleanup and merge! |
Hello,
here is my pull request for #1345. Feel free to leave feedback :)
Franz