def allocate_partially_specified_segment(self, session, **filters): """Allocate model segment from pool partially specified by filters. Return allocated db object or None. """ network_type = self.get_type() with session.begin(subtransactions=True): select = (session.query(self.model).filter_by(allocated=False, **filters)) # Selected segment can be allocated before update by someone else, # We retry until update success or DB_MAX_ATTEMPTS attempts for attempt in range(1, DB_MAX_ATTEMPTS + 1): alloc = select.first() if not alloc: # No resource available return raw_segment = dict((k, alloc[k]) for k in self.primary_keys) LOG.debug( "%(type)s segment allocate from pool, attempt " "%(attempt)s started with %(segment)s ", { "type": network_type, "attempt": attempt, "segment": raw_segment }) count = (session.query(self.model).filter_by( allocated=False, **raw_segment).update({"allocated": True})) if count: LOG.debug( "%(type)s segment allocate from pool, attempt " "%(attempt)s success with %(segment)s ", { "type": network_type, "attempt": attempt, "segment": raw_segment }) return alloc # Segment allocated since select LOG.debug( "Allocate %(type)s segment from pool, " "attempt %(attempt)s failed with segment " "%(segment)s", { "type": network_type, "attempt": attempt, "segment": raw_segment }) LOG.warning( _LW("Allocate %(type)s segment from pool failed " "after %(number)s failed attempts"), { "type": network_type, "number": DB_MAX_ATTEMPTS }) raise exc.NoNetworkFoundInMaximumAllowedAttempts()
def allocate_partially_specified_segment(self, context, **filters): """Allocate model segment from pool partially specified by filters. Return allocated db object or None. """ network_type = self.get_type() session, ctx_manager = self._get_session(context) with ctx_manager: select = (session.query(self.model).filter_by(allocated=False, **filters)) # Selected segment can be allocated before update by someone else, allocs = select.limit(IDPOOL_SELECT_SIZE).all() if not allocs: # No resource available return alloc = random.choice(allocs) raw_segment = dict((k, alloc[k]) for k in self.primary_keys) LOG.debug( "%(type)s segment allocate from pool " "started with %(segment)s ", { "type": network_type, "segment": raw_segment }) count = (session.query(self.model).filter_by( allocated=False, **raw_segment).update({"allocated": True})) if count: LOG.debug( "%(type)s segment allocate from pool " "success with %(segment)s ", { "type": network_type, "segment": raw_segment }) return alloc # Segment allocated since select LOG.debug( "Allocate %(type)s segment from pool " "failed with segment %(segment)s", { "type": network_type, "segment": raw_segment }) # saving real exception in case we exceeded amount of attempts raise db_exc.RetryRequest( exc.NoNetworkFoundInMaximumAllowedAttempts())
def allocate_partially_specified_segment(self, session, **filters): """Allocate model segment from pool partially specified by filters. Return allocated db object or None. """ network_type = self.get_type() with session.begin(subtransactions=True): select = (session.query(self.model).filter_by(allocated=False, **filters)) # Selected segment can be allocated before update by someone else, alloc = select.first() if not alloc: # No resource available return raw_segment = dict((k, alloc[k]) for k in self.primary_keys) LOG.debug( "%(type)s segment allocate from pool " "started with %(segment)s ", { "type": network_type, "segment": raw_segment }) count = (session.query(self.model).filter_by( allocated=False, **raw_segment).update({"allocated": True})) if count: LOG.debug( "%(type)s segment allocate from pool " "success with %(segment)s ", { "type": network_type, "segment": raw_segment }) return alloc # Segment allocated since select LOG.debug( "Allocate %(type)s segment from pool " "failed with segment %(segment)s", { "type": network_type, "segment": raw_segment }) # saving real exception in case we exceeded amount of attempts raise db_exc.RetryRequest( exc.NoNetworkFoundInMaximumAllowedAttempts())