marketplace.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. """
  2. This module represents the Marketplace.
  3. Computer Systems Architecture Course
  4. Assignment 1
  5. March 2020
  6. """
  7. from threading import Lock
  8. class Marketplace:
  9. """
  10. Class that represents the Marketplace. It's the central part of the implementation.
  11. The producers and consumers use its methods concurrently.
  12. """
  13. debug = False
  14. def __init__(self, queue_size_per_producer):
  15. """
  16. Constructor
  17. :type queue_size_per_producer: Int
  18. :param queue_size_per_producer: the maximum size of a queue associated with each producer
  19. """
  20. self.queue_size_per_producer = queue_size_per_producer
  21. self.producer_lock = Lock()
  22. self.consumer_lock = Lock()
  23. self.producers_list = []
  24. self.available_products = []
  25. self.consumers_cart = []
  26. def register_producer(self):
  27. """
  28. Returns an id for the producer that calls this.
  29. """
  30. self.producer_lock.acquire()
  31. producer_id = len(self.producers_list)
  32. self.producers_list.append([])
  33. self.producer_lock.release()
  34. if self.debug:
  35. print("[REG_PROD] NEW")
  36. print("[REG_PROD] Producer " + str(producer_id) + " has registered.")
  37. return producer_id
  38. def publish(self, producer_id, product):
  39. """
  40. Adds the product provided by the producer to the marketplace
  41. :type producer_id: String
  42. :param producer_id: producer id
  43. :type product: Product
  44. :param product: the Product that will be published in the Marketplace
  45. :returns True or False. If the caller receives False, it should wait and then try again.
  46. """
  47. p_id = int(producer_id)
  48. if p_id >= len(self.producers_list):
  49. return False
  50. producer_list = self.producers_list[p_id]
  51. if self.queue_size_per_producer <= len(producer_list):
  52. return False
  53. producer_list.append(product)
  54. self.available_products.append(product)
  55. if self.debug:
  56. print("[PUBLISH] NEW")
  57. print("[PUBLISH] Producer " + str(producer_id) + " inserted element: " + str(product))
  58. print("[PUBLISH] Producer list: " + str(producer_list))
  59. print("[PUBLISH] Available products now: " + str(self.available_products))
  60. return True
  61. def new_cart(self):
  62. """
  63. Creates a new cart for the consumer
  64. :returns an int representing the cart_id
  65. """
  66. self.consumer_lock.acquire()
  67. cart_id = len(self.consumers_cart)
  68. self.consumers_cart.append([])
  69. self.consumer_lock.release()
  70. if self.debug:
  71. print("[NEW_CART] NEW")
  72. print("[NEW_CART] Cart " + str(cart_id) + " created.")
  73. return cart_id
  74. def add_to_cart(self, cart_id, product):
  75. """
  76. Adds a product to the given cart. The method returns
  77. :type cart_id: Int
  78. :param cart_id: id cart
  79. :type product: Product
  80. :param product: the product to add to cart
  81. :returns True or False. If the caller receives False, it should wait and then try again
  82. """
  83. if cart_id >= len(self.consumers_cart) or product not in self.available_products:
  84. return False
  85. self.consumer_lock.acquire()
  86. if product in self.available_products:
  87. self.available_products.remove(product)
  88. self.consumer_lock.release()
  89. self.consumers_cart[cart_id].append(product)
  90. if self.debug:
  91. print("[ADD_TO_CART] NEW")
  92. print("[ADD_TO_CART] Cart " + str(cart_id) + " has new element: " + str(product))
  93. print("[ADD_TO_CART] Cart contents: " + str(self.consumers_cart[cart_id]))
  94. print("[ADD_TO_CART] Available products now: " + str(self.available_products))
  95. return True
  96. def remove_from_cart(self, cart_id, product):
  97. """
  98. Removes a product from cart.
  99. :type cart_id: Int
  100. :param cart_id: id cart
  101. :type product: Product
  102. :param product: the product to remove from cart
  103. """
  104. if cart_id >= len(self.consumers_cart):
  105. return False
  106. cart = self.consumers_cart[cart_id]
  107. if product not in cart:
  108. return False
  109. self.available_products.append(product)
  110. cart.remove(product)
  111. if self.debug:
  112. print("[REMOVE_FROM_CART] NEW")
  113. print("[REMOVE_FROM_CART] Cart " + str(cart_id) + " removed element: " + str(product))
  114. print("[REMOVE_FROM_CART] Cart contents: " + str(cart))
  115. print("[REMOVE_FROM_CART] Available products now: " + str(self.available_products))
  116. return False
  117. def place_order(self, cart_id):
  118. """
  119. Return a list with all the products in the cart.
  120. :type cart_id: Int
  121. :param cart_id: id cart
  122. """
  123. if cart_id >= len(self.consumers_cart):
  124. return None
  125. cart = self.consumers_cart[cart_id]
  126. for product in cart:
  127. found_producer = False
  128. self.producer_lock.acquire()
  129. for producer_list in self.producers_list:
  130. if not found_producer:
  131. for producer_product in producer_list:
  132. if producer_product == product:
  133. producer_list.remove(product)
  134. found_producer = True
  135. else:
  136. if self.debug:
  137. print("[PLACE_ORDER] NEW")
  138. print("[PLACE_ORDER] Cart: " + str(cart))
  139. print("[PLACE_ORDER] Producer " + " has now list: " + str(producer_list))
  140. break
  141. self.producer_lock.release()
  142. return cart