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
Optimize hosts read #454
Optimize hosts read #454
Conversation
) | ||
next { host => names } if names != [] | ||
end | ||
if Ops.greater_than(SCR.Read(path(".target.size"), CFA::Hosts::PATH), 0) |
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.
when doing cleanup this should be replaced too ;-)
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.
well, cfa currently do not have method to recognize if file is not empty or exists. It raise exception. Of course I can use some cli tool to get it
else | ||
Host.Update( | ||
@hostname_initial, | ||
Ops.get_string(@settings, "HOSTNAME", ""), | ||
[Ops.get_string(@settings, "IPADDR", "")] | ||
Ops.get_string(@settings, "IPADDR", "") |
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 didn't check that in details yet so it is more less note for me. Here you change semantics (list of ips -> single ip)
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.
yes, I change API because it is used only as single parameter. I think it do not make much sense to change hostname for more ips, it means you have one hostname for more ips which looks bogus for me.
super(PARSER, PATH, file_handler: file_handler) | ||
end | ||
|
||
def hosts |
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 and some other methods miss documentation.
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.
ok
@@ -27,6 +27,8 @@ | |||
# Authors: Michal Svec <msvec@suse.cz> |
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.
should be removed ;-)
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.
done
def remove_hostname(hostname) | ||
entries = data.select(hostname_matcher(hostname)) | ||
entries.each do |entry| | ||
entry = entry[:value] |
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.
overwriting variable used for iterating in loop is usually not considered to be a good idea.
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.
why not? in ruby it is just variable assigned to some value, but I can create new one if you are more comfortable with it
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.
done
private | ||
|
||
def ip_matcher(ip) | ||
Matcher.new { |k, v| v["ipaddr"] == ip } |
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.
k
is not used so it should be _
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.
done
end | ||
|
||
def hostname_matcher(hostname) | ||
Matcher.new do |k, v| |
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.
as above
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.
done
true | ||
end | ||
|
||
# Dump the Hosts settings to a map, for autoinstallation use. | ||
# @return autoinstallation settings | ||
def Export | ||
return {} if @hosts.empty? | ||
exported_hosts = @hosts.hosts | ||
return {} if exported_hosts.empty? | ||
|
||
# Filter out IPs with empty hostname (so that valid autoyast | ||
# profile is created)(#335120) | ||
# FIXME: this also removes records with empty names from @hosts. Such | ||
# side effect is unexpected and should be removed. |
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.
if I get it correctly this FIXME is no longer true
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.
you are right
require "cfa/augeas_parser" | ||
|
||
module CFA | ||
class Hosts < BaseModel |
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.
For the people that did not design CFA::BaseModel, a comment with the full URL of its API docs will be useful: http://www.rubydoc.info/github/config-files-api/config_files_api/CFA/BaseModel
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.
updated
…maintenance branch SLE-12-SP2" This reverts commit 6a761c7.
ff02::2 ipv6-allrouters | ||
ff02::3 ipv6-allhosts | ||
10.100.128.72 pepa.labs.suse.cz pepa pepa2 | ||
10.254.128.01 pepa1.labs.suse.cz pepa1 |
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.
The "01" is incidental complexity, make that "1".
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.
it is just string for parsing, I do not care about it much
end | ||
|
||
# returns old format of hosts used in Host module. | ||
# @return [Hash<Array<String>>] format is hash where key is ip and value |
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 will rewrite this piece
def set_host(ip, canonical, aliases = []) | ||
entries = data.select(ip_matcher(ip)) | ||
if entries.empty? | ||
log.info "adding new entry for ip #{ip}" |
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.
Ahem, add_entry(ip, canonical, aliases)
instead?
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.
hmm, that cause another search thrue tree searching for ip
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.
What? The body of this if
block is an exact copy of the body of that method, plus return
.
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.
ah, right, add_entry do not search for existing ips, so I will adapt
regarding API, I agree with naming and will change it. But why are you missing those two methods? Does it needed on any place? When I design API I try to avoid adding method that noone need as it is hard to properly design it. E.g. what will be return value? array? or first matching entry? And how it look like? string like now? or hash with canonical and aliases? or only canonical? and for find_by_hostname ( name is confusing for me ) does it return ip or aliases? or hash with all three ( canonical, ip and aliases) ? So if such method someone find useful, then I am not against adding it, when use case is clear. |
@mvidner also thinking about remove_hostname and delete_by_hostname. I also found it confusing. as so for
if I call
|
BTW regarding the |
@mvidner I know, it is a bit misoptimal as it kills comment placement in file. Better way would be direct operation on hosts model and adding, removing and replacing entries there. |
# If it is canonical name, then the first alias becomes the canonical hostname | ||
# @param [String] hostname | ||
# @return [void] | ||
def remove_hostname(hostname) |
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.
Rename this to delete_name
(my original suggestion of delete_by_name
was wrong)
|
||
# Replaces or adds a new host entry. | ||
# If more than one entry with the given ip exists | ||
# then it replaces the last instance. |
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 have a suspicion that with the refactoring of Host.Update we have broken something. I will do some manual tests and report back.
I have now run the code and it says Internal Error, undefined method set_host. This happened when I changed both the IP and the hostname at once. |
|
Regarding the augeas failure: ruby-augeas-0.5.0 needs augeas-1.0.0: hercules-team/ruby-augeas@9025d88
|
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, almost there!
Please add a changelog entry.
thanks |
The issue was raised in installer even with already merged version of the patch. |
checking |
WIP, will be blog entry
rationale for this pr is bug report https://bugzilla.suse.com/show_bug.cgi?id=877047
even with this change I get to less then 20% of original time and found more possible optimization in cfa that will even speed it up.
content for blog:
We get bug report, that yast2 network is slow when there is a lot of entries in /etc/hosts file. We take it as opportunity to tost new profiler support in yast. Profiler shows that problem is in SCR calls, which took a lot of time, so another oppurtinity to test new framework cfa with augeas parser. Augeas have already lense for /etc/hosts file, so it is quite easy to add it. In short here are results for network CLI with /etc/hosts containing ~ 10 000 entries:
before:
after:
We also improved cfa itself
config-files-api/config_files_api#10 which we speed up by 50%.