User Tools

Site Tools


cs330_f2016:labz

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cs330_f2016:labz [2017/03/23 18:31]
dhart
cs330_f2016:labz [2021/06/30 23:42]
Line 1: Line 1:
-====Objective:​==== 
- 
-To gain more significant experience in programming elixir, by implementing a server and constructing a supervisor tree. 
- 
----- 
-====Pre-requisites:​==== 
- 
-For this lab, you will need the [[http://​liftothers.org/​dokuwiki/​doku.php?​id=cs330_f2016:​lab13scaffold|scaffolding code]]. 
- 
-The provided modules create a mock data center with inter module dependencies. ​ 
- 
----- 
-====Deliverable:​==== 
- 
-For this lab, you will code two parts: 
-  - First, you will build a nameserver, for local process registration. 
-  - Second, you will construct a supervisor tree.  The tree should be constructed such that it will automatically restart different "​services"​ in our datacenter if they ever go down. 
- 
----- 
-====Part 1: Name Server:==== 
- 
-In class, we learned that we could put processes on a global process registration system using Process.register(...). However, we want to implement this behavior on a local scale, so only processes that depend on each other know about each other. This is done by implementing a local name server. 
- 
-You will construct a module named NameServer. The purpose of this module is to register names, in the form of atoms, to Pid's. Note that this must be done using your own data structure, such as a map, not the global process registration. 
- 
-The server should accept two synchronous calls, and a single asynchronous call (also known as a cast). 
- 
-<code elixir> 
-#​Synchronous ​ 
-{:register, name} #This will register the given name with the callers pid and return the caller :ok 
-{:resolve, name} #This will return to the caller the pid associated with name, or :error if no such pid can be found 
- 
-#​Asynchronous 
-{:register, name, pid} #register the given name to the given pid, no reply is expected 
-</​code>​ 
- 
-These simple calls allow modules to register themselves with the local name server so that they can easily talk to each other. The name server should return :ok to all other synchronous calls, and discard all other asynchronous calls. You can assume name and Pid are valid. 
- 
-We have provided a skeleton of some GenServer code [[http://​liftothers.org/​dokuwiki/​doku.php?​id=cs330_f2016:​lab13genserver|here]]. 
- 
-Any time a pid goes down you will need to remove it from the name server, this is best done by placing a monitor on the pid before you put it into your data structure. The process will then notify the server through its handle_info function. 
- 
-===Hints:​=== 
- 
-We strongly encourage that your server implements Elixir'​s GenServer behavior. More info is found here. [[https://​hexdocs.pm/​elixir/​GenServer.html| GenServer]] 
- 
-The [[https://​hexdocs.pm/​elixir/​Map.html| Map]] module documentation can be found here. 
- 
-**Elixir can't save your map structure to a global variable. You will need to pass it through the '​state'​ parameter that is the last value at the end of each GenServer function.** 
- 
-Example: 
-<code elixir> 
-def handle_call({:​register,​ name}, pid, mymap) do 
-  ... 
-  {:reply, :ok, mymap} 
-end 
-</​code>​ 
- 
-Monitors are in the Process module, documentation is found [[https://​hexdocs.pm/​elixir/​Process.html#​monitor/​1|here]]. 
- 
----- 
-====Part 2: Supervisor tree:==== 
- 
-You've been asked to construct the supervisor tree for a series of connected modules in a virtual "data center"​. Information for the modules and dependencies can be found below. Each module will be registered in the name server that you coded above. Each process will be started by a node in a supervisor tree. 
- 
-A sample supervisor can be found [[http://​liftothers.org/​dokuwiki/​doku.php?​id=cs330_f2016:​lab13supervisortree|here]]. 
- 
-You must name the highest level supervisor ''​TopSupervisor''​. The module should include ''​start_link/​1''​ which will take a name server as a parameter. You will pass this name server to each of the modules when your supervisors starts them. You will need more than one supervisor node. 
- 
-There are six modules: 
-  * Info 
-  * Order 
-  * User 
-  * CustomerService 
-  * Shipper 
-  * Database 
- 
-They have the following dependencies(A => B is read A depends on B). 
-  *Info => Database 
-  *Order => Database 
-  *Order => User 
-  *Shipper => Database 
-  *User => Database 
-  *User => Order 
- 
-**You must design the tree so when module X goes down, only modules that depend on X are shut down and restarted.** 
- 
-Creating your name server and supervisor tree might look like this: 
-<code elixir> 
-{:ok, name_server} = NameServer.start() 
-response = TopSupervisor.start_link( name_server ) 
-</​code>​ 
-and if you have constructed your tree correctly, it will show output like the following: 
-<code elixir> 
-iex(1)> {response1,​name_server} = NameServer.start_link() 
-{:​ok,<​0.59.0>​} 
-iex(2)> response2 = TopSupervisor.start_link( name_server ) 
-CustomerService has started ​ 
-Database has started 
-Info has started 
-Shipper has started 
-User has started 
-Order has started 
-{ok,<​0.61.0>​} 
-</​code>​ 
- 
-From there, if you have implemented your supervisor properly, you should be able to crash any module without the system going down. The module and its dependencies should just restart and continue working. You can crash a specific module using the included ''​Crasher''​ module. For example, 
- 
-<code elixir> 
-iex(3)> Crasher.crash(name_server,​ :Order) 
-Crashing the module... 
-true 
-Elixir.User has started 
-Elixir.Order has started 
-</​code>​ 
- 
- 
-**Again, you must design the tree so when module X goes down, only modules that depend on X are shut down and restarted.** 
- 
----- 
-===Hints:​=== 
- 
-Don't create your own supervisor, use the built in ''​Supervisor''​ behavior. You will also need to create sub supervisors started by upper level ones. 
- 
-It is helpful to draw your supervisor tree out on paper before starting to program the supervisor trees. 
- 
-To create a name server, call ''​NameServer.start()''​. It will return ''​{ok,​ PID}''​. Pass this pid into the supervisor you are testing. 
- 
-Helpful links:\\ 
-https://​hexdocs.pm/​elixir/​Supervisor.html \\ 
  
cs330_f2016/labz.txt ยท Last modified: 2021/06/30 23:42 (external edit)