VOL-3338:
- Parse PQ ME only with relevant information. Also optimize
  logic of populating the map of TCONT/UNU port entity ID to PQ entity ID.
-  Force adding TCONT to internal DB irrespective of it was added before or not.
- Bump version to 2.4.5

Change-Id: I3ad5a33897ab6b3c5db18d16740b84a13002a452
(cherry picked from commit acb65b077c45d2e0ce6ff50e0b2bddf9c1732705)
diff --git a/VERSION b/VERSION
index 79a6144..59aa62c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.4.4
+2.4.5
diff --git a/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index 4fe1546..a159a91 100644
--- a/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -399,7 +399,7 @@
 
         tcont = OnuTCont.create(self, tcont=tcontdict)
 
-        success = self._pon.add_tcont(tcont)
+        success = self._pon.add_tcont(tcont, True)
         if success:
             new_tconts.append(tcont)
             self.log.debug('pon-add-tcont', tcont=tcont)
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_tp_setup_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_tp_setup_task.py
index 9d2eb09..fbbe86a 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_tp_setup_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_tp_setup_task.py
@@ -162,12 +162,13 @@
     @inlineCallbacks
     def perform_service_specific_steps(self):
         self.log.info('starting-tech-profile-setup', uni_id=self._uni_port.uni_id,
-                        tconts=self._tconts, gem_ports=self._gem_ports, tp_table_id=self._tp_table_id)
+                      tconts=self._tconts, gem_ports=self._gem_ports, tp_table_id=self._tp_table_id)
 
         omci_cc = self._onu_device.omci_cc
         gem_pq_associativity = dict()
         pq_to_related_port = dict()
         is_related_ports_configurable = False
+        tcont_entity_id = 0
 
         try:
             ################################################################################
@@ -197,6 +198,9 @@
             tcont_idents = self._onu_device.query_mib(Tcont.class_id)
             self.log.debug('tcont-idents', tcont_idents=tcont_idents)
 
+            # There can be only one tcont that can be installed per tech-profile download task
+            # Each tech-profile represents a single tcont and associated gemports
+            assert len(self._tconts) == 1
             for tcont in self._tconts:
                 self.log.debug('tcont-loop', tcont=tcont)
 
@@ -220,8 +224,13 @@
                     # Also assign entity id within tcont object
                     results = yield tcont.add_to_hardware(omci_cc, free_entity_id)
                     self.check_status_and_state(results, 'new-tcont-added')
+                    # There is only tcont to be added per tech-profile download procedure
+                    # So, there is no issue of overwriting the 'tcont_entity_id'
+                    tcont_entity_id = free_entity_id
+
                 else:
                     self.log.debug('tcont-already-assigned', tcont_entity_id=tcont.entity_id, alloc_id=tcont.alloc_id)
+                    tcont_entity_id = tcont.entity_id
 
             ################################################################################
             # GEMS  (GemPortNetworkCtp and GemInterworkingTp)
@@ -269,29 +278,32 @@
                 except TypeError:
                     continue
 
-                if 'instance_id' in v:
+                # Parse PQ MEs only with relevant information
+                if 'instance_id' in v and 'related_port' in v['attributes']:
                     related_port = v['attributes']['related_port']
                     pq_to_related_port[k] = related_port
-
+                    # If the MSB is set, it represents an Upstream PQ referencing the TCONT
                     if v['instance_id'] & 0b1000000000000000:
-                        tcont_me = (related_port & 0xffff0000) >> 16
-                        if tcont_me not in self.tcont_me_to_queue_map:
-                            self.log.debug("prior-q-related-port-and-tcont-me",
-                                           related_port=related_port,
-                                           tcont_me=tcont_me)
-                            self.tcont_me_to_queue_map[tcont_me] = list()
+                        # If it references the TCONT ME we have just installed
+                        if tcont_entity_id == (related_port & 0xffff0000) >> 16:
+                            if tcont_entity_id not in self.tcont_me_to_queue_map:
+                                self.log.debug("prior-q-related-port-and-tcont-me",
+                                               related_port=related_port,
+                                               tcont_me=tcont_entity_id)
+                                self.tcont_me_to_queue_map[tcont_entity_id] = list()
+                            # Store the PQ into the list which is referenced by TCONT ME we have provisioned
+                            self.tcont_me_to_queue_map[tcont_entity_id].append(k)
 
-                        self.tcont_me_to_queue_map[tcont_me].append(k)
                     else:
-                        uni_port = (related_port & 0xffff0000) >> 16
-                        if uni_port == self._uni_port.entity_id:
-                            if uni_port not in self.uni_port_to_queue_map:
+                        # This represents the PQ pointing to the UNI Port ME (Downstream PQ)
+                        if self._uni_port.entity_id == (related_port & 0xffff0000) >> 16:
+                            if self._uni_port.entity_id not in self.uni_port_to_queue_map:
                                 self.log.debug("prior-q-related-port-and-uni-port-me",
                                                related_port=related_port,
-                                               uni_port_me=uni_port)
-                                self.uni_port_to_queue_map[uni_port] = list()
-
-                            self.uni_port_to_queue_map[uni_port].append(k)
+                                               uni_port_me=self._uni_port.entity_id)
+                                self.uni_port_to_queue_map[self._uni_port.entity_id] = list()
+                            # Store the PQ into the list which is referenced by UNI Port ME we have provisioned
+                            self.uni_port_to_queue_map[self._uni_port.entity_id].append(k)
 
             self.log.debug("ul-prior-q", ul_prior_q=self.tcont_me_to_queue_map)
             self.log.debug("dl-prior-q", dl_prior_q=self.uni_port_to_queue_map)
diff --git a/python/adapters/brcm_openomci_onu/pon_port.py b/python/adapters/brcm_openomci_onu/pon_port.py
index 634fd7e..2ee3344 100644
--- a/python/adapters/brcm_openomci_onu/pon_port.py
+++ b/python/adapters/brcm_openomci_onu/pon_port.py
@@ -177,7 +177,8 @@
             return False # already created
 
         self.log.info('add-tcont', tcont=tcont.alloc_id, reflow=reflow)
-        self._tconts[tcont.alloc_id] = tcont
+        if tcont.alloc_id not in self._tconts:
+            self._tconts[tcont.alloc_id] = tcont
         return True
 
     @inlineCallbacks