CMT202 Demonstrate and apply knowledge about the state-of-the-art in distributed-systems architectures.

Distributed and Cloud Computing

Learning Outcome 1: Demonstrate and apply knowledge about the state-of-the-art in distributed-systems architectures.

Learning Outcome 2: Appreciate the difference between various distributed computing middleware and their communication mechanisms.

Assignment
You have been hired by a library to build a distributed data storage system using a remote object paradigm that will allow one to store and access information relating to copies of books, authors of books and users who loan copies of books.

Each author has the following two associated pieces of information which should be stored in the system:

Author name.
Author genre which refers to the type of books written by the author (e.g. crime, fiction).
Each book copy has the following two associated pieces of information which should be stored in the system:

Book author.
Book title.
Note, multiple copies of a single book can exist in the system. You can assume that each book has a unique title.

Each user has the following two associated pieces of information which should be stored in the system:

User name.
User contact phone number.
Design and implement the above distributed data storage system using a remote object paradigm which allows library employees to perform the following twelve tasks:

Task 1

Add a user to the system. Implement this using a method with the following header:

def add_user(self, user_name, user_number)

An example of calling this method is:

rental_object.add_user("Allen Hatcher", 123456)

You can assume that each user added to the system has a unique user name.

Task 2

Return all associated pieces of information relating to the set of users currently stored in the system (i.e. a set of user names and contact numbers). Implement this using a method with the following header:

def return_users(self)

An example of calling this method is:

rental_object.return_users()

The information returned by this method should have the property that it can be easily interpreted when displayed using the Python print function. That is, the output from the following print function should be easily interpreted and understood by a human reader:

print(rental_object.return_users())

Task 3

Add an author to the system. Implement this using a method with the following header:

def add_author(self, author_name, author_genre):

An example of calling this method is:

library_object.add_author("James Joyce", "fiction")

You can assume that all author names are unique.

Task 4

Return all associated pieces of information relating to the set of authors currently stored in the system (i.e. a set of author names plus genres). Implement this using a method with the following header:

def return_authors(self)

An example of calling this method is:

library_object.return_authors()

The information returned by this method should have the property that it can be easily interpreted when displayed using the Python print function.

Task 5

Add a copy of a book to the system. Implement this using a method with the following header:

def add_book_copy(self, author_name, book_title)

An example of calling this method is:

library_object.add_book_copy("James Joyce", "Ulysses")

When a book copy is first added to the system it is initially not loaned to any user. Multiple copies of a single book (books with the same author and title) may be added to the system.

You can assume that all book titles are unique.

Task 6

Return all associated pieces of information relating to the set of book copies currently not on loan (i.e. a set of book authors plus titles). Implement this using a method with the following header:

def return_books_not_loan(self)

An example of calling this method is:

library_object.return_books_not_loan()

Note, multiple copies of a single book can exist in the system.

The information returned by this method should have the property that it can be easily interpreted when displayed using the Python print function.

Task 7

Loan a copy of a specified book to a specified user on a specified date. Implement this using a method with the following header:

def loan_book(self, user_name, book_title, year, month, day)

An example of calling this method is:

library_object.loan_book("Conor Reilly", "Ulysses", 2019, 1, 3)

Each copy of a book can only be loaned to a single user at a time. For example, consider the case where there are two copies of a given book and both are currently on loan. In this case the book in question cannot be loaned until one of the copies is returned or an additional copy is added to the system.

The method loan_book should return a value of 1 if the book in question was successfully loaned. Otherwise, the method should return a value of 0.

Task 8

Return all associated pieces of information relating to the set of book copies currently on loan (i.e. a set of book authors plus titles). Implement this using a method with the following header:

def return_books_loan(self)

An example of calling this method is:

library_object.return_books_loan()

The information returned by this method should have the property that it can be easily interpreted when displayed using the Python print function.

Task 9

Return to the library a loaned copy of a specified book by a specified user on a specified date; that is, set the status of the book in question from loaned to not loaned. Implement this using a method with the following header:

def end_book_loan(self, user_name, book_title, year, month, day)

An example of calling this method is:

library_object.end_book_loan("Conor Reilly", "Ulysses", 2019, 2, 4)

You can assume that a user will only loan one copy of a given book at any one time. Therefore, there will never exist any ambiguity regarding which book copy is being returned.

Task 10

Delete from the system all copies of a specified book which are currently not on loan. Copies which are currently on loan should not be deleted. Implement this using a method with the following header:

def delete_book(self, book_title)

An example of calling this method is:

library_object.delete_book("Ulysses")

Task 11

Delete from the system a specified user. A user should only be deleted if they currently are not loaning and have never loaned a book. Implement this using a method with the following header:

def delete_user(self, user_name)

An example of calling this method is:

library_object.delete_user("Conor Reilly")

The method delete_user should return a value of 1 if the user in question was deleted. Otherwise, the method should return a value of 0.

Task 12

Return all book titles a user previously has loaned where the corresponding loan and return dates both lie between a specified start and end date inclusive.

Implement this using a method with the following header:

def user_loans_date(self, user_name, start_year, start_month, start_day, end_year, end_month, end_day)

An example of calling this method is:

library_object.user_loans_date("Conor Reilly", 2010, 1, 1, 2029, 2, 1)

Note, the book titles returned may contain duplicates if the user loaned the book in question more than once.

The information returned by this method should have the property that it can be easily interpreted when displayed using the Python print function.

In your solution, the class in question should be called library. That is, when defining the class use the expression "class library(object):". Also, the class must be contained in a file entitled library.py.

In the file library.py you should create an object of type library and register this object with the name server using the name example.library. That is, the file library.py should contain the following code snippet:

daemon = Daemon()

serve({library: "example.library"}, daemon=daemon, use_ns=True)