<s> """<STR_LIT>""" <EOL> __author__ = '<STR_LIT>' <EOL> from pyon . core import bootstrap <EOL> from pyon . core . bootstrap import CFG <EOL> from pyon . core . exception import Inconsistent , BadRequest <EOL> from pyon . datastore . datastore import DataStore <EOL> from pyon . ion . event import EventPublisher , EventSubscriber <EOL> from pyon . ion . identifier import create_unique_directory_id <EOL> from pyon . util . log import log <EOL> from pyon . util . containers import get_ion_ts <EOL> from interface . objects import DirEntry <EOL> class Directory ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , orgname = None , datastore_manager = None , events_enabled = False , container = None ) : <EOL> self . container = container or bootstrap . container_instance <EOL> datastore_manager = datastore_manager or self . container . datastore_manager <EOL> self . dir_store = datastore_manager . get_datastore ( DataStore . DS_DIRECTORY , DataStore . DS_PROFILE . DIRECTORY ) <EOL> self . orgname = orgname or CFG . system . root_org <EOL> self . is_root = ( self . orgname == CFG . system . root_org ) <EOL> self . events_enabled = events_enabled <EOL> self . event_pub = None <EOL> self . event_sub = None <EOL> def start ( self ) : <EOL> if CFG . system . auto_bootstrap : <EOL> root_de = self . register ( "<STR_LIT:/>" , "<STR_LIT>" , sys_name = bootstrap . get_sys_name ( ) ) <EOL> if root_de is None : <EOL> pass <EOL> if self . events_enabled : <EOL> self . event_pub = EventPublisher ( ) <EOL> self . event_sub = EventSubscriber ( event_type = "<STR_LIT>" , <EOL> origin = "<STR_LIT>" , <EOL> callback = self . receive_directory_change_event ) <EOL> def stop ( self ) : <EOL> self . close ( ) <EOL> def close ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . event_sub : <EOL> self . event_sub . deactivate ( ) <EOL> self . dir_store . close ( ) <EOL> def _get_path ( self , parent , key ) : <EOL> """<STR_LIT>""" <EOL> if parent == "<STR_LIT:/>" : <EOL> return parent + key <EOL> elif parent . startswith ( "<STR_LIT:/>" ) : <EOL> return parent + "<STR_LIT:/>" + key <EOL> else : <EOL> raise BadRequest ( "<STR_LIT>" % parent ) <EOL> def _get_key ( self , path ) : <EOL> """<STR_LIT>""" <EOL> parent , key = path . rsplit ( "<STR_LIT:/>" , <NUM_LIT:1> ) <EOL> return key <EOL> def _create_dir_entry ( self , parent , key , orgname = None , ts = None , attributes = None ) : <EOL> """<STR_LIT>""" <EOL> orgname = orgname or self . orgname <EOL> ts = ts or get_ion_ts ( ) <EOL> attributes = attributes if attributes is not None else { } <EOL> parent = parent or "<STR_LIT:/>" <EOL> de = DirEntry ( org = orgname , parent = parent , key = key , attributes = attributes , ts_created = ts , ts_updated = ts ) <EOL> return de <EOL> def _read_by_path ( self , path , orgname = None ) : <EOL> """<STR_LIT>""" <EOL> if path is None : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> orgname = orgname or self . orgname <EOL> parent , key = path . rsplit ( "<STR_LIT:/>" , <NUM_LIT:1> ) <EOL> parent = parent or "<STR_LIT:/>" <EOL> find_key = [ orgname , key , parent ] <EOL> view_res = self . dir_store . find_by_view ( '<STR_LIT>' , '<STR_LIT>' , key = find_key , id_only = True , convert_doc = True ) <EOL> match = [ doc for docid , index , doc in view_res ] <EOL> if len ( match ) > <NUM_LIT:1> : <EOL> log . warn ( "<STR_LIT>" % path ) <EOL> recent_match = self . _cleanup_outdated_entries ( match , "<STR_LIT>" % path ) <EOL> return recent_match <EOL> elif match : <EOL> return match [ <NUM_LIT:0> ] <EOL> return None <EOL> def _cleanup_outdated_entries ( self , dir_entries , common = "<STR_LIT:key>" ) : <EOL> """<STR_LIT>""" <EOL> if not dir_entries : <EOL> return <EOL> newest_entry = dir_entries [ <NUM_LIT:0> ] <EOL> try : <EOL> for de in dir_entries : <EOL> if int ( de . ts_updated ) > int ( newest_entry . ts_updated ) : <EOL> newest_entry = de <EOL> remove_list = [ de for de in dir_entries if de is not newest_entry ] <EOL> log . info ( "<STR_LIT>" % remove_list ) <EOL> for de in remove_list : <EOL> try : <EOL> self . dir_store . delete ( de ) <EOL> except Exception as ex : <EOL> log . warn ( "<STR_LIT>" % ( common , de ) ) <EOL> log . info ( "<STR_LIT>" % ( len ( remove_list ) , common ) ) <EOL> except Exception as ex : <EOL> log . warn ( "<STR_LIT>" % ( <EOL> common , str ( ex ) ) ) <EOL> return newest_entry <EOL> def lookup ( self , parent , key = None , return_entry = False ) : <EOL> """<STR_LIT>""" <EOL> path = self . _get_path ( parent , key ) if key else parent <EOL> direntry = self . _read_by_path ( path ) <EOL> if return_entry : <EOL> return direntry <EOL> else : <EOL> return direntry . attributes if direntry else None <EOL> def _get_unique_parents ( self , entry_list ) : <EOL> """<STR_LIT>""" <EOL> if entry_list and type ( entry_list ) not in ( list , tuple ) : <EOL> entry_list = [ entry_list ] <EOL> parents = set ( ) <EOL> for entry in entry_list : <EOL> parents . add ( entry . parent ) <EOL> if "<STR_LIT:/>" in parents : <EOL> parents . remove ( "<STR_LIT:/>" ) <EOL> return sorted ( parents ) <EOL> def _ensure_parents_exist ( self , entry_list , create = True ) : <EOL> parents_list = self . _get_unique_parents ( entry_list ) <EOL> pe_list = [ ] <EOL> try : <EOL> for parent in parents_list : <EOL> pe = self . lookup ( parent ) <EOL> if pe is None : <EOL> pp , pk = parent . rsplit ( "<STR_LIT:/>" , <NUM_LIT:1> ) <EOL> direntry = self . _create_dir_entry ( parent = pp , key = pk ) <EOL> pe_list . append ( direntry ) <EOL> if create : <EOL> self . dir_store . create ( direntry , create_unique_directory_id ( ) ) <EOL> except Exception as ex : <EOL> log . warn ( "<STR_LIT>" , exc_info = True ) <EOL> return pe_list <EOL> def register ( self , parent , key , create_only = False , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if not ( parent and key ) : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> if not type ( parent ) is str or not parent . startswith ( "<STR_LIT:/>" ) : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> dn = self . _get_path ( parent , key ) <EOL> log . debug ( "<STR_LIT>" , dn , kwargs ) <EOL> entry_old = None <EOL> cur_time = get_ion_ts ( ) <EOL> direntry = self . _read_by_path ( dn ) <EOL> if direntry and create_only : <EOL> return direntry <EOL> elif direntry : <EOL> entry_old = direntry . attributes <EOL> direntry . attributes = kwargs <EOL> direntry . ts_updated = cur_time <EOL> self . dir_store . update ( direntry ) <EOL> else : <EOL> direntry = self . _create_dir_entry ( parent , key , attributes = kwargs , ts = cur_time ) <EOL> self . _ensure_parents_exist ( [ direntry ] ) <EOL> self . dir_store . create ( direntry , create_unique_directory_id ( ) ) <EOL> return entry_old <EOL> def register_safe ( self , parent , key , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> return self . register ( parent , key , ** kwargs ) <EOL> except Exception as ex : <EOL> log . exception ( "<STR_LIT>" % ( parent , key , kwargs ) ) <EOL> def register_mult ( self , entries ) : <EOL> """<STR_LIT>""" <EOL> if type ( entries ) not in ( list , tuple ) : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> de_list = [ ] <EOL> cur_time = get_ion_ts ( ) <EOL> for parent , key , attrs in entries : <EOL> direntry = self . _create_dir_entry ( parent , key , attributes = attrs , ts = cur_time ) <EOL> de_list . append ( direntry ) <EOL> pe_list = self . _ensure_parents_exist ( de_list , create = False ) <EOL> de_list . extend ( pe_list ) <EOL> deid_list = [ create_unique_directory_id ( ) for i in xrange ( len ( de_list ) ) ] <EOL> self . dir_store . create_mult ( de_list , deid_list ) <EOL> def unregister ( self , parent , key = None , return_entry = False ) : <EOL> """<STR_LIT>""" <EOL> path = self . _get_path ( parent , key ) if key else parent <EOL> log . debug ( "<STR_LIT>" % path ) <EOL> direntry = self . _read_by_path ( path ) <EOL> if direntry : <EOL> self . dir_store . delete ( direntry ) <EOL> if direntry and not return_entry : <EOL> return direntry . attributes <EOL> else : <EOL> return direntry <EOL> def unregister_safe ( self , parent , key ) : <EOL> try : <EOL> return self . unregister ( parent , key ) <EOL> except Exception as ex : <EOL> log . exception ( "<STR_LIT>" % ( parent , key ) ) <EOL> def find_child_entries ( self , parent = '<STR_LIT:/>' , direct_only = True , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if not type ( parent ) is str or not parent . startswith ( "<STR_LIT:/>" ) : <EOL> raise BadRequest ( "<STR_LIT>" % parent ) <EOL> if direct_only : <EOL> start_key = [ self . orgname , parent , <NUM_LIT:0> ] <EOL> end_key = [ self . orgname , parent ] <EOL> res = self . dir_store . find_by_view ( '<STR_LIT>' , '<STR_LIT>' , <EOL> start_key = start_key , end_key = end_key , id_only = True , convert_doc = True , ** kwargs ) <EOL> else : <EOL> path = parent [ <NUM_LIT:1> : ] . split ( "<STR_LIT:/>" ) <EOL> start_key = [ self . orgname , path , <NUM_LIT:0> ] <EOL> end_key = [ self . orgname , list ( path ) + [ "<STR_LIT>" ] ] <EOL> res = self . dir_store . find_by_view ( '<STR_LIT>' , '<STR_LIT>' , <EOL> start_key = start_key , end_key = end_key , id_only = True , convert_doc = True , ** kwargs ) <EOL> match = [ value for docid , indexkey , value in res ] <EOL> return match <EOL> def find_by_key ( self , key = None , parent = '<STR_LIT:/>' , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if key is None : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> if parent is None : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> start_key = [ self . orgname , key , parent ] <EOL> end_key = [ self . orgname , key , parent + "<STR_LIT>" ] <EOL> res = self . dir_store . find_by_view ( '<STR_LIT>' , '<STR_LIT>' , <EOL> start_key = start_key , end_key = end_key , id_only = True , convert_doc = True , ** kwargs ) <EOL> match = [ value for docid , indexkey , value in res ] <EOL> return match <EOL> def find_by_value ( self , subtree = '<STR_LIT:/>' , attribute = None , value = None , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if attribute is None : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> if subtree is None : <EOL> raise BadRequest ( "<STR_LIT>" ) <EOL> start_key = [ self . orgname , attribute , value , subtree ] <EOL> end_key = [ self . orgname , attribute , value , subtree + "<STR_LIT>" ] <EOL> res = self . dir_store . find_by_view ( '<STR_LIT>' , '<STR_LIT>' , <EOL> start_key = start_key , end_key = end_key , id_only = True , convert_doc = True , ** kwargs ) <EOL> match = [ value for docid , indexkey , value in res ] <EOL> return match <EOL> def remove_child_entries ( self , parent , delete_parent = False ) : <EOL> pass <EOL> def _assert_existence ( self , parent , key , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> dn = self . _get_path ( parent , key ) <EOL> direntry = self . _safe_read ( dn ) <EOL> existed = bool ( direntry ) <EOL> if not direntry : <EOL> cur_time = get_ion_ts ( ) <EOL> parent_dn = self . _get_path ( parent ) <EOL> direntry = DirEntry ( parent = parent_dn , key = key , attributes = kwargs , ts_created = cur_time , ts_updated = cur_time ) <EOL> self . dir_store . create ( direntry , dn ) <EOL> return existed <EOL> def receive_directory_change_event ( self , event_msg , headers ) : <EOL> pass </s>
