#NEWLINE# def create_object_with_dependency( creator , dep_getter , dep_creator , dep_id_attr ) : #NEWLINE# #INDENT# 'Creates an object that binds to a dependency while handling races.\n\n    creator is a function that expected to take the result of either\n    dep_getter or dep_creator.\n\n    The result of dep_getter and dep_creator must have an attribute of\n    dep_id_attr be used to determine if the dependency changed during object\n    creation.\n\n    dep_getter should return None if the dependency does not exist\n\n    dep_creator can raise a DBDuplicateEntry to indicate that a concurrent\n    create of the dependency occured and the process will restart to get the\n    concurrently created one\n\n    This function will return both the created object and the dependency it\n    used/created.\n\n    This function protects against all of the cases where the dependency can\n    be concurrently removed by catching exceptions and restarting the\n    process of creating the dependency if one no longer exists. It will\n    give up after neutron.db.api.MAX_RETRIES and raise the exception it\n    encounters after that.\n\n    TODO(kevinbenton): currently this does not try to delete the dependency\n    it created. This matches the semantics of the HA network logic it is used\n    for but it should be modified to cleanup in the future.\n    ' #NEWLINE# ( result , dependency , dep_id ) = ( None , None , None ) #NEWLINE# for attempts in range ( 1 , ( db_api . MAX_RETRIES + 1 ) ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# dependency = ( dep_getter ( ) or dep_creator ( ) ) #NEWLINE# dep_id = getattr ( dependency , dep_id_attr ) #NEWLINE# #UNINDENT# except db_exc . DBDuplicateEntry : #NEWLINE# #INDENT# with excutils . save_and_reraise_exception ( ) as ctx : #NEWLINE# #INDENT# if ( attempts < db_api . MAX_RETRIES ) : #NEWLINE# #INDENT# time . sleep ( random . uniform ( 0 , 1 ) ) #NEWLINE# ctx . reraise = False #NEWLINE# continue #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# try : #NEWLINE# #INDENT# result = creator ( dependency ) #NEWLINE# break #NEWLINE# #UNINDENT# except Exception : #NEWLINE# #INDENT# with excutils . save_and_reraise_exception ( ) as ctx : #NEWLINE# #INDENT# if ( attempts < db_api . MAX_RETRIES ) : #NEWLINE# #INDENT# dependency = dep_getter ( ) #NEWLINE# if ( ( not dependency ) or ( dep_id != getattr ( dep_id_attr , dep_id_attr ) ) ) : #NEWLINE# #INDENT# ctx . reraise = False #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# return ( result , dependency )