Skip to content

Commit

Permalink
Merge pull request #518 from Igalia/named-apps
Browse files Browse the repository at this point in the history
#482 - Introduce named programs
  • Loading branch information
xray7224 committed Nov 4, 2016
2 parents 044dfd8 + 9dfb3c8 commit 3f41d9a
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 12 deletions.
63 changes: 63 additions & 0 deletions src/core/app.lua
Expand Up @@ -12,6 +12,7 @@ local histogram = require('core.histogram')
local counter = require("core.counter")
local zone = require("jit.zone")
local jit = require("jit")
local S = require("syscall")
local ffi = require("ffi")
local C = ffi.C
require("core.packet_h")
Expand All @@ -25,6 +26,9 @@ local use_restart = false

test_skipped_code = 43

-- Set the directory for the named programs.
named_program_root = shm.root .. "/" .. "by-name"

-- The set of all active apps and links in the system.
-- Indexed both by name (in a table) and by number (in an array).
app_table, app_array = {}, {}
Expand Down Expand Up @@ -124,6 +128,50 @@ function configure (new_config)
counter.add(configs)
end

-- Claims a name for a program so it's identified by name by other processes.
--
-- The name given to the function must be unique; if a name has been used before
-- by an active process the function will error displaying an appropriate error
-- message. The program can only claim one name, successive calls will produce
-- an error.
function claim_name(name)
configuration[name] = name
local namedir = "by-name/" .. name
local namedir_fq = named_program_root .. "/" .. name
local piddir = shm.root .. "/" .. S.getpid()
local backlinkdir = piddir.."/name"

-- Verify that the by-name directory exists.
shm.mkdir(namedir)

-- Verify that we've not already claimed a name
assert(configuration.name == nil, "Name already claimed, cannot claim: "..name)

-- Create the new symlink.
assert(S.symlink(piddir, namedir_fq))

-- Create a backlink so to the symlink so we can easily cleanup
assert(S.symlink(namedir_fq, backlinkdir))
end

-- Enumerates the named programs with their PID
--
-- This returns a table programs with the key being the name of the program
-- and the value being the PID of the program. Each program is checked that
-- it's still alive. Any dead program or program without a name is not listed.
function enumerate_named_programs()
local progs = {}
local dirs = shm.children("/by-name")
if dirs == nil then return progs end
for _, program in pairs(dirs) do
local fq = named_program_root .. "/" .. program
local piddir = S.readlink(fq)
local pid = tonumber(lib.basename(piddir))
if S.kill(pid, 0) then progs[lib.basename(fq)] = pid end
end
return progs
end

-- Return the configuration actions needed to migrate from old config to new.
--
-- Here is an example return value for a case where two apps must
Expand Down Expand Up @@ -526,4 +574,19 @@ function selftest ()
assert(app_table.app3 == orig_app3) -- should be the same
main({duration = 4, report = {showapps = true}})
assert(app_table.app3 ~= orig_app3) -- should be restarted

-- Test claiming and enumerating app names
local basename = "testapp"
claim_name(basename.."1")

-- Ensure to claim two names fails
assert(not pcall(claim_name, basename.."2"))

-- Check if it can be enumerated.
local progs = enumerate_named_programs()
assert(progs)
assert(progs["testapp1"])

-- Ensure that trying to take the same name fails
assert(not pcall(claim_name, basename.."1"))
end
6 changes: 6 additions & 0 deletions src/core/main.lua
Expand Up @@ -142,6 +142,12 @@ end
-- Cleanup after Snabb process.
function shutdown (pid)
if not _G.developer_debug and not lib.getenv("SNABB_SHM_KEEP") then
-- Try cleaning up symlinks for named apps, if none exist, fail silently.
local backlink = shm.root.."/"..pid.."/name"
local name_link = S.readlink(backlink)
S.unlink(name_link)
S.unlink(backlink)

shm.unlink("/"..pid)
end
end
Expand Down
30 changes: 18 additions & 12 deletions src/program/top/top.lua
Expand Up @@ -32,25 +32,31 @@ function run (args)
end

function select_snabb_instance (pid)
local instances = shm.children("/")
local function compute_snabb_instances()
-- Produces set of snabb instances, excluding this one.
local pids = {}
local my_pid = S.getpid()
for _, name in ipairs(shm.children("/")) do
-- This could fail as the name could be for example "by-name"
local p = tonumber(name)
if p and p ~= my_pid then table.insert(pids, p) end
end
return pids
end

local instances = compute_snabb_instances()

if pid then
-- Try to use given pid
for _, instance in ipairs(instances) do
if instance == pid then return pid end
end
print("No such Snabb instance: "..pid)
elseif #instances == 1 then print("No Snabb instance found.")
elseif #instances == 1 then return instances[1]
elseif #instances <= 0 then print("No Snabb instance found.")
else
local own_pid = tostring(S.getpid())
if #instances == 2 then
-- Two means one is us, so we pick the other.
return instances[1] == own_pid and instances[2] or instances[1]
else
print("Multiple Snabb instances found. Select one:")
for _, instance in ipairs(instances) do
if instance ~= own_pid then print(instance) end
end
end
print("Multiple Snabb instances found. Select one:")
for _, instance in ipairs(instances) do print(instance) end
end
main.exit(1)
end
Expand Down

0 comments on commit 3f41d9a

Please sign in to comment.