X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/5964efeaa53eb62b51b814b67ff413f0593a03a0..9ba558e8b4fa1b132e834c1fbab074a3ac848169:/examples/lua/chord/chord.lua diff --git a/examples/lua/chord/chord.lua b/examples/lua/chord/chord.lua index 687d485d80..523b15017c 100644 --- a/examples/lua/chord/chord.lua +++ b/examples/lua/chord/chord.lua @@ -13,12 +13,12 @@ fix_fingers_delay = 120 check_predecessor_delay = 120 lookup_delay = 10 --- current node (don't worry, globals are duplicated in each process) +-- current node (don't worry, globals are duplicated in each simulated process) my_node = { id = my_id, next_finger_to_fix = 1, fingers = {}, - predecessor = nil + predecessor = nil, comm_recv = nil } @@ -26,18 +26,30 @@ my_node = { -- Arguments: -- - my id -- - the id of a guy I know in the system (except for the first node) -function node(my_id, known_id) +function node(...) + + -- TODO simplify the deployment file + local known_id + local args = {...} + my_node.id = tonumber(args[1]) + if #args == 4 then + known_id = tonumber(args[2]) + end - simgrid.info("Hello, I'm a node") + -- initialize the node + for i = 1, nb_bits do + my_node.fingers[i] = my_node.id + end + my_node.comm_recv = simgrid.task.irecv(my_node.id) -- join the ring - local success = false + local join_success = false if known_id == nil then -- first node create() - success = true + join_success = true else - success = join(known_id) + join_success = join(known_id) end -- main loop @@ -49,17 +61,19 @@ function node(my_id, known_id) local next_check_predecessor_date = now + check_predecessor_delay local next_lookup_date = now + lookup_delay - local task - my_node.comm_recv = simgrid.task.irecv(my_node.id) + local task, err while now < max_simulation_time do - task = simgrid.comm.test(node.comm_recv) + task, err = my_node.comm_recv:test() if task then -- I received a task: answer it my_node.comm_recv = simgrid.task.irecv(my_node.id) handle_task(task) + elseif err then + -- the communication has failed: nevermind + my_node.comm_recv = simgrid.task.irecv(my_node.id) else -- no task was received: do periodic calls if now >= next_stabilize_date then @@ -73,6 +87,7 @@ function node(my_id, known_id) elseif now >= next_check_predecessor_date then check_predecessor() next_check_predecessor_date = simgrid.get_clock() + check_predecessor_delay + elseif now >= next_lookup_date then random_lookup() next_lookup_date = simgrid.get_clock() + lookup_delay @@ -90,31 +105,49 @@ function node(my_id, known_id) end end +-- Makes the current node leave the ring +function leave() + + simgrid.info("Leaving the ring") + -- TODO: notify others +end + -- This function is called when the current node receives a task. -- - task: the task received function handle_task(task) - local type = task[type] + local type = task.type if type == "find successor" then + simgrid.info("Received a 'find successor' request from " .. task.answer_to .. + " for id " .. task.request_id) + -- is my successor the successor? - if is_in_interval(task[request_id], my_node.id + 1, my_node.fingers[1]) then - task[type] = "find successor answer" - task[answer] = my_node.fingers[1] - task:dsend(task[answer_to]) + if is_in_interval(task.request_id, my_node.id + 1, my_node.fingers[1]) then + + simgrid.info("Sending back a 'find successor answer' to " .. + task.answer_to .. ": the successor of " .. task.request_id .. + " is " .. my_node.fingers[1]) + + task.type = "find successor answer" + task.answer = my_node.fingers[1] + task:dsend(task.answer_to) else -- forward the request to the closest preceding finger in my table - task:dsend(closest_preceding_node(task[request_id])) + + simgrid.info("Forwarding the 'find successor' request to my closest preceding finger") + task:dsend(closest_preceding_node(task.request_id)) end elseif type == "get predecessor" then - task[answer] = my_node.predecessor - task:dsend(task[answer_to]) + task.type = "get predecessor answer" + task.answer = my_node.predecessor + task:dsend(task.answer_to) elseif type == "notify" then -- someone is telling me that he may be my new predecessor - notify(task[request_id]) + notify(task.request_id) elseif type == "predecessor leaving" then -- TODO @@ -129,7 +162,7 @@ function handle_task(task) -- ignoring else - error("Unknown type of task received: " .. task[type]) + error("Unknown type of task received: " .. task.type) end end @@ -160,6 +193,36 @@ function is_in_interval(id, a, b) return id <= b end +-- Returns whether the current node is in the ring. +function has_joined() + + return my_node.fingers[1] ~= nil +end + +-- Creates a new Chord ring. +function create() + my_node.predecessor = nil + my_node.fingers[1] = my_node.id +end + +-- Attemps to join the Chord ring. +-- - known_id: id of a node already in the ring +-- - return value: true if the join was successful +function join(known_id) + + simgrid.info("Joining the ring with id " .. my_node.id .. ", knowing node " .. known_id) + + local successor = remote_find_successor(known_id, my_node.id) + if successor == nil then + simgrid.info("Cannot join the ring.") + return false + end + + my_node.predecessor = nil + my_node.fingers[1] = successor + return true +end + -- Returns the closest preceding finger of an id with respect to the finger -- table of the current node. -- - id: the id to find @@ -167,16 +230,16 @@ end function closest_preceding_node(id) for i = nb_bits, 1, -1 do - if is_in_interval(my_node.fingers[i].id, my_node.id + 1, id - 1) then + if is_in_interval(my_node.fingers[i], my_node.id + 1, id - 1) then -- finger i is the first one before id - return my_node.fingers[i].id + return my_node.fingers[i] end end end -- Finds the successor of an id -- id: the id to find --- return value: the id of the successor, or -1 if the request failed +-- return value: the id of the successor, or nil if the request failed function find_successor(id) if is_in_interval(id, my_node.id + 1, my_node.fingers[1]) then @@ -195,31 +258,43 @@ end -- return value: the id of the successor, or nil if the request failed function remote_find_successor(ask_to, id) - local task = simgrid.task.new(comp_size, comm_size) - task[type] = "find successor" - task[request_id] = id - task[answer_to] = my_node.id + local task = simgrid.task.new("", comp_size, comm_size) + task.type = "find successor" + task.request_id = id + task.answer_to = my_node.id + simgrid.info("Sending a 'find successor' request to " .. ask_to .. " for id " .. id) if task:send(ask_to, timeout) then -- request successfully sent: wait for an answer + + simgrid.info("Sent the 'find successor' request to " .. ask_to .. + " for id " .. id .. ", waiting for the answer") + while true do - task = simgrid.comm.wait(my_node.comm_recv, timeout) + task = my_node.comm_recv:wait(timeout) my_node.comm_recv = simgrid.task.irecv(my_node.id) if not task then -- failed to receive the answer + simgrid.info("Failed to receive the answer to my 'find successor' request") return nil else -- a task was received: is it the expected answer? - if task[type] ~= "find successor answer" or task[request_id] ~= id then + if task.type ~= "find successor answer" or task.request_id ~= id then -- this is not our answer + simgrid.info("Received another request of type " .. task.type) handle_task(task) else -- this is our answer - return task[answer] + simgrid.info("Received the answer to my 'find successor' request for id " .. + id .. ": the successor is " .. task.answer) + return task.answer end end end + else + simgrid.info("Failed to send the 'find successor' request to " .. ask_to .. + " for id " .. id) end return successor @@ -230,14 +305,14 @@ end -- return value: the id of its predecessor, or nil if the request failed function remote_get_predecessor(ask_to) - local task = simgrid.task.new(comp_size, comm_size) - task[type] = "get predecessor" - task[answer_to] = my_node.id + local task = simgrid.task.new("", comp_size, comm_size) + task.type = "get predecessor" + task.answer_to = my_node.id if task:send(ask_to, timeout) then -- request successfully sent: wait for an answer while true do - task = simgrid.comm.wait(my_node.comm_recv, timeout) + task = my_node.comm_recv:wait(timeout) my_node.comm_recv = simgrid.task.irecv(my_node.id) if not task then @@ -245,13 +320,13 @@ function remote_get_predecessor(ask_to) return nil else -- a task was received: is it the expected answer? - if task[type] ~= "get predecessor answer" then + if task.type ~= "get predecessor answer" then -- this is not our answer handle_task(task) else -- this is our answer -- FIXME make sure the message answers to this particular request - return task[answer] + return task.answer end end end @@ -272,7 +347,7 @@ function stabilize() end -- this node is a candidate to become my new successor - if candidate ~= nil and is_in_interval(candidate, my_node.id + 1, successor -1) then + if candidate ~= nil and is_in_interval(candidate, my_node.id + 1, successor - 1) then my_node.fingers[1] = candidate end @@ -296,9 +371,9 @@ end -- - candidate the possible new predecessor function remote_notify(notify_to, candidate_predecessor) - local task = simgrid.task.new(comp_size, comm_size) - task[type] = "notify" - task[request_id] = candidate_predecessor + local task = simgrid.task.new("", comp_size, comm_size) + task.type = "notify" + task.request_id = candidate_predecessor task:dsend(notify_to) end @@ -309,7 +384,7 @@ function fix_fingers() local id = find_successor(my_node.id + 2^i) if id ~= nil then if id ~= my_node.fingers[i] then - fingers[i] = id + my_node.fingers[i] = id end my_node.next_finger_to_fix = (i % nb_bits) + 1 end