Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
New Lua example: Chord (work in progress)
authorChristophe Thiéry <christopho128@gmail.com>
Thu, 10 Nov 2011 17:46:50 +0000 (18:46 +0100)
committerChristophe Thiéry <christopho128@gmail.com>
Thu, 10 Nov 2011 17:48:56 +0000 (18:48 +0100)
examples/lua/chord/chord.lua [new file with mode: 0644]

diff --git a/examples/lua/chord/chord.lua b/examples/lua/chord/chord.lua
new file mode 100644 (file)
index 0000000..643408c
--- /dev/null
@@ -0,0 +1,172 @@
+-- A SimGrid Lua implementation of the Chord DHT
+
+require("simgrid")
+
+nb_bits = 24
+nb_keys = 2^nb_bits
+comp_size = 0
+comm_size = 10
+timeout = 50
+max_simulation_time = 1000
+stabilize_delay = 20
+fix_fingers_delay = 120
+check_predecessor_delay = 120
+lookup_delay = 10
+
+-- current node (globals are duplicated in each process)
+my_node = {
+  id = my_id,
+  next_finger_to_fix = 1,
+  fingers = {},
+  predecessor = nil
+  comm_recv = nil
+}
+
+-- Main function of each Chord process
+-- Arguments:
+-- - my id
+-- - the id of a guy I know in the system (except for the first node)
+function node(my_id, known_id)
+
+  simgrid.info("Hello, I'm a node")
+  --
+  -- join the ring
+  local success = false
+  if known_id == nil then
+    -- first node
+    create()
+    success = true
+  else
+    success = join(known_id)
+  end
+
+  -- main loop
+  if join_success then
+
+    local now = simgrid.get_clock()
+    local next_stabilize_date = now + stabilize_delay
+    local next_fix_fingers_date = now + fix_fingers_delay
+    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)
+
+    while simgrid.get_clock() < max_simulation_time do
+
+      task = simgrid.comm.test(node.comm_recv)
+
+      if task then
+       -- I received a task: answer it
+        my_node.comm_recv = simgrid.task.irecv(my_node.id)
+       handle_task(task)
+      else
+        -- no task was received: do periodic calls
+       if simgrid.get_clock() >= next_fix_fingers_date then
+       
+       end
+      end
+    end
+    leave()
+  end
+end
+
+-- Returns whether an id belongs to the interval [a, b[.
+-- The parameters are noramlized to make sure they are between 0 and nb_keys - 1).
+-- 1 belongs to [62, 3].
+-- 1 does not belong to [3, 62].
+-- 63 belongs to [62, 3].
+-- 63 does not belong to [3, 62].
+-- 24 belongs to [21, 29].
+-- 24 does not belong to [29, 21].
+function is_in_interval(id, a, b)
+
+  -- normalize the parameters
+  id = id % nb_bits
+  a = a % nb_bits
+  b = b % nb_bits
+  -- make sure a <= b and a <= id
+  if b < a then
+    b = b + nb_keys
+  end
+
+  if id < a then
+    id = id + nb_keys
+  end
+
+  return id <= b
+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
+function find_successor(d)
+
+  if is_in_interval(id, my_node.id + 1, my_node.fingers[1]) then
+    -- my successor is the successor
+    return my_node.fingers[1]
+  end
+
+  -- ask to the closest preceding finger in my table
+  local ask_to = closest_preceding_node(id)
+  return remote_find_successor(ask_to, id)
+end
+
+-- Asks a remote node the successor of an id.
+-- ask_to: id of a remote node to ask to
+-- id: the id to find
+-- return value: the id of the successor, or -1 if the request failed
+function remote_find_successor(ask_to, id)
+
+  local successor
+  local task = simgrid.task.new(comp_size, comm_size)
+  task[type] = "find successor"
+  task[request_id] = id
+  task[issuer] = my_node.id
+
+  if task:send(ask_to, timeout) then
+    -- request successfully sent: wait for an answer
+    local stop = false
+    repeat
+      task = simgrid.comm.wait(my_node.comm_recv, timeout)
+      my_node.comm_recv = simgrid.task.irecv(my_node.id)
+    
+      if not task then
+       -- failed to receiver the answer
+        stop = true
+      else
+       -- a task was received: is it the expected answer?
+       if task[type] ~= "find successor" or task[request_id] ~= id then
+          -- this is not our anwser
+         handle_task(task)
+       else
+         -- this is our answer
+         successor = task[answer_id]
+         stop = true
+       end
+      end
+    until stop
+  end
+
+  return successor
+end
+
+-- Returns the closest preceding finger of an id with respect to the finger
+-- table of the current node.
+-- - id: the id to find
+-- - return value: the closest preceding finger of that id
+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
+      -- finger i is the first one before id
+      return my_node.fingers[i].id
+    end
+  end
+end
+
+simgrid.platform(arg[1] or "../../msg/msg_platform.xml")
+simgrid.application(arg[2] or "../../msg/chord/chord90.xml")
+simgrid.run()
+