<s> """<STR_LIT>""" <EOL> __author__ = '<STR_LIT>' <EOL> import logging <EOL> import struct <EOL> import zlib <EOL> from collections import deque <EOL> from functools import partial <EOL> from viewfinder . backend . base import util <EOL> from viewfinder . backend . db import db_client , vf_schema <EOL> from viewfinder . backend . db . base import DBObject <EOL> from viewfinder . backend . db . hash_base import DBHashObject <EOL> @ DBObject . map_table_attributes <EOL> class IdAllocator ( DBHashObject ) : <EOL> """<STR_LIT>""" <EOL> __slots__ = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' ] <EOL> _START_ID = <NUM_LIT:1> <EOL> _DEFAULT_ALLOCATION = <NUM_LIT:7> <EOL> _table = DBObject . _schema . GetTable ( vf_schema . ID_ALLOCATOR ) <EOL> _instances = list ( ) <EOL> def __init__ ( self , id_type = None , allocation = None ) : <EOL> """<STR_LIT>""" <EOL> super ( IdAllocator , self ) . __init__ ( ) <EOL> self . id_type = id_type <EOL> self . _allocation = allocation or IdAllocator . _DEFAULT_ALLOCATION <EOL> self . _next_id_key = self . _table . GetColumn ( '<STR_LIT>' ) . key <EOL> self . _cur_id = IdAllocator . _START_ID <EOL> self . _last_id = IdAllocator . _START_ID <EOL> self . _allocation_pending = False <EOL> self . _waiters = deque ( ) <EOL> IdAllocator . _instances . append ( self ) <EOL> def Reset ( self ) : <EOL> assert len ( self . _waiters ) == <NUM_LIT:0> , self . _waiters <EOL> assert not self . _allocation_pending <EOL> self . _cur_id = IdAllocator . _START_ID <EOL> self . _last_id = IdAllocator . _START_ID <EOL> self . _allocation_pending = False <EOL> def NextId ( self , client , callback ) : <EOL> """<STR_LIT>""" <EOL> if self . _allocation_pending : <EOL> self . _waiters . append ( partial ( self . _AllocateId , callback ) ) <EOL> elif self . _cur_id == self . _last_id : <EOL> self . _waiters . append ( partial ( self . _AllocateId , callback ) ) <EOL> self . _AllocateIds ( client ) <EOL> else : <EOL> self . _AllocateId ( callback ) <EOL> def _AllocateId ( self , callback , type = None , value = None , traceback = None ) : <EOL> """<STR_LIT>""" <EOL> if ( type , value , traceback ) != ( None , None , None ) : <EOL> raise type , value , traceback <EOL> assert self . _cur_id < self . _last_id <EOL> new_id = self . _cur_id <EOL> self . _cur_id += <NUM_LIT:1> <EOL> callback ( new_id ) <EOL> def _ProcessWaiters ( self ) : <EOL> """<STR_LIT>""" <EOL> while len ( self . _waiters ) and self . _cur_id < self . _last_id : <EOL> self . _waiters . popleft ( ) ( ) <EOL> return len ( self . _waiters ) == <NUM_LIT:0> <EOL> def _AllocateIds ( self , client ) : <EOL> """<STR_LIT>""" <EOL> assert self . _cur_id == self . _last_id , ( self . _cur_id , self . _last_id ) <EOL> def _OnAllocate ( result ) : <EOL> self . _last_id = result . return_values [ self . _next_id_key ] <EOL> if self . _last_id <= IdAllocator . _START_ID : <EOL> self . _cur_id = self . _last_id <EOL> return self . _AllocateIds ( client ) <EOL> self . _cur_id = max ( IdAllocator . _START_ID , self . _last_id - self . _allocation ) <EOL> assert self . _cur_id < self . _last_id , '<STR_LIT>' % ( self . _cur_id , self . _last_id ) <EOL> logging . debug ( "<STR_LIT>" % <EOL> ( self . _allocation , self . id_type , self . _cur_id , self . _last_id ) ) <EOL> if not self . _ProcessWaiters ( ) : <EOL> self . _AllocateIds ( client ) <EOL> else : <EOL> self . _allocation_pending = False <EOL> def _OnError ( type , value , traceback ) : <EOL> logging . error ( '<STR_LIT>' , exc_info = ( type , value , traceback ) ) <EOL> while len ( self . _waiters ) : <EOL> self . _waiters . popleft ( ) ( type , value , traceback ) <EOL> self . _allocation_pending = True <EOL> with util . MonoBarrier ( _OnAllocate , on_exception = _OnError ) as b : <EOL> client . UpdateItem ( table = self . _table . name , key = self . GetKey ( ) , <EOL> attributes = { self . _next_id_key : <EOL> db_client . UpdateAttr ( value = self . _allocation , action = '<STR_LIT>' ) } , <EOL> return_values = '<STR_LIT>' , callback = b . Callback ( ) ) <EOL> @ staticmethod <EOL> def ComputeHashPrefix ( id , num_bytes = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> assert num_bytes - <NUM_LIT:1> in xrange ( <NUM_LIT:4> ) , num_bytes <EOL> return zlib . crc32 ( struct . pack ( '<STR_LIT>' , id ) ) & [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] [ num_bytes - <NUM_LIT:1> ] <EOL> @ classmethod <EOL> def ResetState ( cls ) : <EOL> """<STR_LIT>""" <EOL> for id_alloc in IdAllocator . _instances : <EOL> id_alloc . Reset ( ) </s>
