<s> """<STR_LIT>""" <EOL> __author__ = '<STR_LIT>' <EOL> import json <EOL> import logging <EOL> import os <EOL> import sys <EOL> import time <EOL> from tornado import gen , options <EOL> from viewfinder . backend . base import constants , main , util <EOL> from viewfinder . backend . logs import logs_util <EOL> from viewfinder . backend . storage . object_store import ObjectStore <EOL> from viewfinder . backend . storage import store_utils <EOL> from viewfinder . backend . services . provisioning_profiles import AppleProvisioningProfile , TestFlightDevices <EOL> options . define ( '<STR_LIT>' , default = None , help = '<STR_LIT>' ) <EOL> options . define ( '<STR_LIT>' , default = None , help = '<STR_LIT>' ) <EOL> options . define ( '<STR_LIT>' , default = <NUM_LIT> , help = '<STR_LIT>' ) <EOL> options . define ( '<STR_LIT>' , default = <NUM_LIT> , help = '<STR_LIT>' ) <EOL> @ gen . coroutine <EOL> def GetFileList ( merged_store , marker ) : <EOL> """<STR_LIT>""" <EOL> base_path = '<STR_LIT>' <EOL> marker = os . path . join ( base_path , marker ) <EOL> file_list = yield gen . Task ( store_utils . ListAllKeys , merged_store , prefix = base_path , marker = marker ) <EOL> file_list . sort ( ) <EOL> raise gen . Return ( file_list ) <EOL> @ gen . coroutine <EOL> def GetUDIDTimestamps ( merged_store , files ) : <EOL> """<STR_LIT>""" <EOL> last_seen = { } <EOL> for f in files : <EOL> contents = yield gen . Task ( merged_store . Get , f ) <EOL> dev_list = json . loads ( contents ) <EOL> for entry in dev_list : <EOL> timestamp = entry [ '<STR_LIT>' ] <EOL> device_dict = entry [ '<STR_LIT>' ] . get ( '<STR_LIT>' , entry [ '<STR_LIT>' ] . get ( '<STR_LIT>' , None ) ) <EOL> if not device_dict : <EOL> continue <EOL> udid = device_dict . get ( '<STR_LIT>' , None ) <EOL> if not udid : <EOL> continue <EOL> prev_seen = last_seen . get ( udid , <NUM_LIT:0> ) <EOL> if timestamp > prev_seen : <EOL> last_seen [ udid ] = timestamp <EOL> raise gen . Return ( last_seen ) <EOL> @ gen . engine <EOL> def Start ( callback ) : <EOL> assert options . options . apple or options . options . testflight , '<STR_LIT>' <EOL> assert options . options . search_days > <NUM_LIT:0> <EOL> if options . options . apple : <EOL> assert not options . options . testflight , '<STR_LIT>' <EOL> devices = AppleProvisioningProfile ( options . options . apple ) . Devices ( ) <EOL> else : <EOL> devices = TestFlightDevices ( options . options . testflight ) . Devices ( ) <EOL> logs_paths = logs_util . ServerLogsPaths ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> merged_store = ObjectStore . GetInstance ( logs_paths . MERGED_LOGS_BUCKET ) <EOL> start_time = time . time ( ) - ( options . options . search_days + <NUM_LIT:1> ) * constants . SECONDS_PER_DAY <EOL> start_date = util . TimestampUTCToISO8601 ( start_time ) <EOL> files = yield GetFileList ( merged_store , start_date ) <EOL> logging . info ( '<STR_LIT>' % ( len ( devices ) , len ( files ) ) ) <EOL> last_seen = yield GetUDIDTimestamps ( merged_store , files ) <EOL> missing = [ ] <EOL> by_age = [ ] <EOL> valid = [ ] <EOL> now = time . time ( ) <EOL> for d in devices : <EOL> if d not in last_seen : <EOL> missing . append ( d ) <EOL> else : <EOL> age = ( now - last_seen [ d ] ) / constants . SECONDS_PER_DAY <EOL> if age > options . options . inactive_days : <EOL> by_age . append ( ( age , d ) ) <EOL> else : <EOL> valid . append ( d ) <EOL> by_age . sort ( ) <EOL> print '<STR_LIT>' % len ( valid ) <EOL> print '<STR_LIT>' % ( options . options . search_days , len ( missing ) ) <EOL> if missing : <EOL> print '<STR_LIT:U+0020>' + '<STR_LIT>' . join ( missing ) <EOL> print '<STR_LIT>' % len ( by_age ) <EOL> for ( age , device ) in by_age : <EOL> print '<STR_LIT>' % ( age , device ) <EOL> callback ( ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> sys . exit ( main . InitAndRun ( Start ) ) </s>
