def non_leaf_coalesce(node, parent, uri, cb):
    node_vhd = node.vhd
    parent_vhd = parent.vhd

    log.debug("non_leaf_coalesce key={}, parent={}".format(node_vhd.id, parent_vhd.id))

    opq = cb.volumeStartOperations(uri, 'w')
    meta_path = cb.volumeMetadataGetPath(opq)

    node_path = cb.volumeGetPath(opq, str(node_vhd.id))
    log.debug("Running vhd-coalesce on {}".format(node_vhd.id))
    VHDUtil.coalesce(GC, node_path)

    db = VHDMetabase(meta_path)
    with Lock(opq, 'gl', cb):
        # reparent all of the children to this node's parent
        children = db.get_children(node_vhd.id)

        with db.write_context():
            journal_entries = db.add_journal_entries(node_vhd.id, parent_vhd.id, children)

        __reparent_children(opq, db, cb, journal_entries)

        # remove key
        log.debug("Destroy {}".format(node_vhd.id))
        cb.volumeDestroy(opq, str(node_vhd.id))
        with db.write_context():
            db.delete_vhd(node_vhd.id)

        cb.volumeUnlock(opq, node.lock)
        cb.volumeUnlock(opq, parent.lock)

    db.close()
    cb.volumeStopOperations(opq)
def recover_journal(uri, cb):
    opq = cb.volumeStartOperations(uri, 'w')
    meta_path = cb.volumeMetadataGetPath(opq)
    db = VHDMetabase(meta_path)

    # Take the global SR lock, the coaleasce reparenting happens within this
    # lock, so if we can get it and if there are any pending operations then
    # a different process crashed or was aborted and we need to complete
    # the outstanding operations
    with Lock(opq, 'gl', cb):
        # First get any leaf VDIs that need a tap refresh
        refresh_entries = db.get_refresh_entries()
        __refresh_leaf_vdis(opq, db, cb, refresh_entries)

        # Now get the journalled reparent operations
        journal_entries = db.get_journal_entries()
        __reparent_children(opq, db, cb, journal_entries)
def find_best_non_leaf_coalesceable_2(uri, cb):
    opq = cb.volumeStartOperations(uri, 'w')
    meta_path = cb.volumeMetadataGetPath(opq)
    db = VHDMetabase(meta_path)

    ret = (None, None)
    with Lock(opq, 'gl', cb):
        nodes = find_non_leaf_coalesceable(db)
        for node in nodes:
            parent_lock = cb.volumeTryLock(opq, __create_vhd_lock_name(node.parent_id))
            if parent_lock:
                node_lock = cb.volumeTryLock(opq, __create_vhd_lock_name(node.id))
                if node_lock:
                    parent = db.get_vhd_by_id(node.parent_id)
                    ret = (VhdLock(node, node_lock), VhdLock(parent, parent_lock))
                    break
                else:
                    cb.volumeUnlock(opq, parent_lock)
    db.close()
    cb.volumeStopOperations(opq)
    return ret
def remove_garbage_vhds(uri, cb):
    opq = cb.volumeStartOperations(uri, 'w')
    meta_path = cb.volumeMetadataGetPath(opq)
    db = VHDMetabase(meta_path)

    garbage = db.get_garbage_vhds()

    if len(garbage) > 0:
        for vhd in garbage:
            cb.volumeDestroy(opq, str(vhd.id))
            with db.write_context():
                db.delete_vhd(vhd.id)
    db.close()
    cb.volumeStopOperations(opq)