def __compactify_remove_index_async( cls, volume_id, parent_id, dead_file_id, dead_dir_index ): """ Remove a freed index slot's node data. """ idx_key_name = MSEntryDirEntIndex.make_key_name( volume_id, parent_id, dead_dir_index ) ent_key_name = MSEntryEntDirIndex.make_key_name( volume_id, dead_file_id ) idx_key = storagetypes.make_key( MSEntryDirEntIndex, idx_key_name ) ent_key = storagetypes.make_key( MSEntryEntDirIndex, ent_key_name ) @storagetypes.concurrent def delete_index_if_unallocated(): idx_node = yield idx_key.get_async( use_cache=False, use_memcache=False ) if idx_node is None: # already gone storagetypes.concurrent_return( 0 ) if not idx_node.alloced: yield idx_key.delete_async() storagetypes.concurrent_return( 0 ) yield ent_key.delete_async(), storagetypes.transaction_async( delete_index_if_unallocated ) storagetypes.memcache.delete_multi( [idx_key_name, ent_key_name] )
def __update_or_alloc_async( cls, volume_id, parent_id, file_id, dir_index, generation, alloced ): """ Update or allocate the index node pair and/or set the directory index node's allocation status, asynchronously. If the directory index node does not exist, it and its entry index node will be created and the allocation status set accordingly. If the directory index node exists, but has a different allocation status, then the allocation status will be set accordingly. If we succeed in allocating a new index node, incremenet the number of children in the parent directory. Return True on success. Return False if the index node existed, but the file_id did not match its record or the allocation status did not change. """ index_key_name = MSEntryDirEntIndex.make_key_name( volume_id, parent_id, dir_index ) nonce = random.randint( -2**63, 2**63 - 1 ) result = True idx = yield MSEntryDirEntIndex.get_or_insert_async( index_key_name, volume_id=volume_id, parent_id=parent_id, file_id=file_id, dir_index=dir_index, generation=generation, alloced=alloced, nonce=nonce ) if idx.nonce == nonce: # created. if alloced: logging.info("Directory /%s/%s: allocated index slot for /%s/%s at %s" % (volume_id, parent_id, volume_id, file_id, dir_index)) else: logging.info("Directory /%s/%s: freed index slot at %s" % (volume_id, parent_id, dir_index)) # need to create an entry index node as well. entry_key_name = MSEntryEntDirIndex.make_key_name( volume_id, file_id ) entry_key = storagetypes.make_key( MSEntryEntDirIndex, entry_key_name ) entry_idx = MSEntryEntDirIndex( key=entry_key, volume_id=volume_id, parent_id=parent_id, file_id=file_id, dir_index=dir_index, generation=generation, alloced=alloced, nonce=nonce ) yield entry_idx.put_async() else: # already exists. changing allocation status? if idx.alloced != alloced: # allocation status needs to be changed # want to change allocation status rc = yield storagetypes.transaction_async( lambda: cls.__update_index_node_async( volume_id, parent_id, file_id, dir_index, alloced, generation=generation ), xg=True ) if rc == 0: result = True else: logging.error("__update_index_node_async(/%s/%s file_id=%s dir_index=%s alloced=%s) rc = %s" % (volume_id, parent_id, file_id, dir_index, alloced, rc )) result = False else: if alloced and idx.file_id != file_id: # collision on insertion logging.error("Directory /%s/%s: collision inserting /%s/%s at %s (occupied by /%s/%s)" % (volume_id, parent_id, volume_id, file_id, dir_index, volume_id, idx.file_id)) result = False else: # created/set correctly result = True storagetypes.concurrent_return( result )
def swap( free_file_id ): rc, alloced_idx, free_idx_file_id = yield storagetypes.transaction_async( lambda: do_swap( free_file_id ), xg=True ) if rc < 0: storagetypes.concurrent_return( rc ) old_dir_index = None if free_file_id is None: free_file_id = free_idx_file_id if free_file_id is not None: # blow away the newly-freed index node old_entry_idx_key_name = MSEntryEntDirIndex.make_key_name( volume_id, free_file_id ) old_entry_idx_key = storagetypes.make_key( MSEntryEntDirIndex, old_entry_idx_key_name ) yield old_entry_idx_key.delete_async() storagetypes.memcache.delete( old_entry_idx_key_name ) old_dir_index = alloced_idx.dir_index storagetypes.concurrent_return( old_dir_index )