Skip to content

Commit

Permalink
Extract PropertyTable to its own library
Browse files Browse the repository at this point in the history
*Backwards incompatible - please read*

PropertyTable is now its own library and it has been simplified. While
some API affecting changes to PropertyTable were made in the library to
fix bugs, improve performance and make it more generic, this preserves
the PropertyTable semantics as much as possible to avoid application
code needing to change. I don't believe any user code should need to
change.

The backwards incompatible part of this change is that all references to
`VintageNet.PropertyTable` need to be changed to `PropertyTable`. This
shouldn't affect most code, but does affect `vintage_net_wifi`.

This fixes #352.
  • Loading branch information
fhunleth committed Apr 26, 2022
1 parent 5ee4317 commit 5f969c8
Show file tree
Hide file tree
Showing 18 changed files with 95 additions and 698 deletions.
48 changes: 35 additions & 13 deletions lib/vintage_net.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule VintageNet do
[github.com/nerves-networking/vintage_net](https://github.com/nerves-networking/vintage_net)
for more information.
"""
alias VintageNet.{Info, Interface, PropertyTable}
alias VintageNet.{Info, Interface}

@typedoc """
A name for the network interface
Expand Down Expand Up @@ -104,6 +104,32 @@ defmodule VintageNet do
"""
@type info_options :: {:redact, boolean()}

@typedoc """
A VintageNet property
VintageNet uses lists of strings to name networking configuration and status
items.
"""
@type property :: [String.t()]

@typedoc """
A pattern for matching against VintageNet properties
Patterns are used when subscribing for network property changes or getting a
set of properties and their values.
Since properties are organized hierarchically, the default way of matching patterns is to match on prefixes. It's also
possible to use the `:_` wildcard to match anything at a position.
"""
@type pattern :: [String.t() | :_ | :"$"]

@typedoc """
A property's value
See the `README.md` for documenation on available properties.
"""
@type value :: any()

@doc """
Return a list of all interfaces on the system
"""
Expand Down Expand Up @@ -233,7 +259,7 @@ defmodule VintageNet do
interface) and `match/1` to run wildcard matches (i.e., get a specific
property for all interfaces).
"""
@spec get(PropertyTable.property(), PropertyTable.value()) :: PropertyTable.value()
@spec get(property(), value()) :: value()
def get(name, default \\ nil) do
PropertyTable.get(VintageNet, name, default)
end
Expand All @@ -244,11 +270,9 @@ defmodule VintageNet do
Patterns are list of strings that optionally specify `:_` at
a position in the list to match any value.
"""
@spec match(PropertyTable.property_with_wildcards()) :: [
{PropertyTable.property(), PropertyTable.value()}
]
@spec match(pattern()) :: [{property(), value()}]
def match(pattern) do
PropertyTable.match(VintageNet, pattern)
PropertyTable.match(VintageNet, pattern ++ [:"$"]) |> Enum.sort()
end

@doc """
Expand All @@ -257,11 +281,9 @@ defmodule VintageNet do
To get a list of all known properties and their values, call
`VintageNet.get_by_prefix([])`
"""
@spec get_by_prefix(PropertyTable.property()) :: [
{PropertyTable.property(), PropertyTable.value()}
]
def get_by_prefix(prefix) do
PropertyTable.get_by_prefix(VintageNet, prefix)
@spec get_by_prefix(property()) :: [{property(), value()}]
def get_by_prefix(pattern) do
PropertyTable.match(VintageNet, pattern) |> Enum.sort()
end

@doc """
Expand All @@ -287,15 +309,15 @@ defmodule VintageNet do
VintageNet.subscribe(["interface", :_, "addresses"])
```
"""
@spec subscribe(PropertyTable.property_with_wildcards()) :: :ok
@spec subscribe(pattern()) :: :ok
def subscribe(name) do
PropertyTable.subscribe(VintageNet, name)
end

@doc """
Stop subscribing to property change messages
"""
@spec unsubscribe(PropertyTable.property_with_wildcards()) :: :ok
@spec unsubscribe(pattern()) :: :ok
def unsubscribe(name) do
PropertyTable.unsubscribe(VintageNet, name)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/vintage_net/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule VintageNet.Application do
properties = load_initial_configurations() |> Enum.map(&config_to_property/1)

children = [
{VintageNet.PropertyTable, properties: properties, name: VintageNet},
{PropertyTable, properties: properties, name: VintageNet, tuple_events: true},
{VintageNet.PredictableInterfaceName, hw_path_ifnames},
VintageNet.PowerManager.Supervisor,
{BEAMNotify,
Expand Down
2 changes: 1 addition & 1 deletion lib/vintage_net/info.ex
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ defmodule VintageNet.Info do
defp sanitize_configuration(data), do: data

defp format_if_attribute(ifname, name, print_name, print_since? \\ false) do
case VintageNet.PropertyTable.fetch_with_timestamp(VintageNet, ["interface", ifname, name]) do
case PropertyTable.fetch_with_timestamp(VintageNet, ["interface", ifname, name]) do
{:ok, value, timestamp} ->
[
" ",
Expand Down
14 changes: 9 additions & 5 deletions lib/vintage_net/interface.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule VintageNet.Interface do
use GenStateMachine

alias VintageNet.Interface.{CommandRunner, RawConfig}
alias VintageNet.{Persistence, PredictableInterfaceName, PropertyTable, RouteManager}
alias VintageNet.{Persistence, PredictableInterfaceName, RouteManager}
alias VintageNet.PowerManager.PMControl
alias VintageNet.Technology.Null

Expand Down Expand Up @@ -223,7 +223,9 @@ defmodule VintageNet.Interface do
nil ->
# No configuration, so use a null config and fix the property table
raw_config = null_raw_config(ifname)

PropertyTable.put(VintageNet, ["interface", ifname, "config"], raw_config.source_config)

raw_config

config ->
Expand Down Expand Up @@ -677,8 +679,8 @@ defmodule VintageNet.Interface do

@impl GenStateMachine
def terminate(_reason, _state, %{ifname: ifname}) do
PropertyTable.clear(VintageNet, ["interface", ifname, "type"])
PropertyTable.clear(VintageNet, ["interface", ifname, "state"])
PropertyTable.delete(VintageNet, ["interface", ifname, "type"])
PropertyTable.delete(VintageNet, ["interface", ifname, "state"])
end

defp start_configuring(new_config, data, actions) do
Expand Down Expand Up @@ -731,8 +733,10 @@ defmodule VintageNet.Interface do
ifname = data.ifname
config = data.config

PropertyTable.put(VintageNet, ["interface", ifname, "type"], config.type)
PropertyTable.put(VintageNet, ["interface", ifname, "state"], state)
PropertyTable.put_many(VintageNet, [
{["interface", ifname, "type"], config.type},
{["interface", ifname, "state"], state}
])

if state != :configured do
# Once a state is `:configured`, then the configuration provides the connection
Expand Down
8 changes: 2 additions & 6 deletions lib/vintage_net/interface/udhcpd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@ defmodule VintageNet.Interface.Udhcpd do
def lease_update(ifname, lease_file) do
case parse_leases(lease_file) do
{:ok, leases} ->
VintageNet.PropertyTable.put(
VintageNet,
["interface", ifname, "dhcpd", "leases"],
leases
)
PropertyTable.put(VintageNet, ["interface", ifname, "dhcpd", "leases"], leases)

{:error, _} ->
Logger.error("#{ifname}: Failed to handle lease update from #{lease_file}")

VintageNet.PropertyTable.clear_prefix(VintageNet, ["interface", ifname, "dhcpd", "leases"])
PropertyTable.delete_matches(VintageNet, ["interface", ifname, "dhcpd", "leases"])
end
end

Expand Down
13 changes: 8 additions & 5 deletions lib/vintage_net/interfaces_monitor/info.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule VintageNet.InterfacesMonitor.Info do
@moduledoc false

alias VintageNet.{IP, PropertyTable}
alias VintageNet.IP

@link_if_properties [:lower_up, :mac_address]
@address_if_properties [:addresses]
Expand Down Expand Up @@ -142,7 +142,7 @@ defmodule VintageNet.InterfacesMonitor.Info do
@spec clear_properties(VintageNet.ifname()) :: :ok
def clear_properties(ifname) do
Enum.each(@all_if_properties, fn property ->
PropertyTable.clear(VintageNet, ["interface", ifname, to_string(property)])
PropertyTable.delete(VintageNet, ["interface", ifname, to_string(property)])
end)
end

Expand All @@ -151,8 +151,11 @@ defmodule VintageNet.InterfacesMonitor.Info do
"""
@spec update_present(t()) :: t()
def update_present(%__MODULE__{ifname: ifname} = info) do
PropertyTable.put(VintageNet, ["interface", ifname, "present"], true)
PropertyTable.put(VintageNet, ["interface", ifname, "hw_path"], info.hw_path)
PropertyTable.put_many(VintageNet, [
{["interface", ifname, "present"], true},
{["interface", ifname, "hw_path"], info.hw_path}
])

info
end

Expand All @@ -169,7 +172,7 @@ defmodule VintageNet.InterfacesMonitor.Info do
end

defp update_link_property(ifname, property, nil) do
PropertyTable.clear(VintageNet, ["interface", ifname, to_string(property)])
PropertyTable.delete(VintageNet, ["interface", ifname, to_string(property)])
end

defp update_link_property(ifname, property, value) do
Expand Down
166 changes: 0 additions & 166 deletions lib/vintage_net/property_table.ex

This file was deleted.

Loading

0 comments on commit 5f969c8

Please sign in to comment.