package com.atlassian.stash.internal.db;

import com.atlassian.stash.internal.maintenance.latch.Latch;
import com.atlassian.stash.internal.maintenance.latch.LatchMode;

import javax.annotation.Nonnull;

/**
 * Describes a latch over the system database. This latch includes both the {@code DataSource} and the Hibernate
 * {@code SessionFactory}. While the latch is held, attempts to open new database connections or start Hibernate
 * sessions will block. Note that all other operations against the {@code SessionFactory} will also block, not
 * just creating new sessions.
 * <p>
 * <b>Warning</b>: A <i>best effort</i> is made to allow existing connections/sessions to continue processing
 * normally, but it is possible they will also be blocked in certain circumstances. When that happens, the latch
 * will be unable to {@link #drain(long, java.util.concurrent.TimeUnit) drain}.
 *
 * @see com.atlassian.stash.internal.db.DatabaseManager#acquireLatch(LatchMode)
 */
public interface DatabaseLatch extends Latch {

    /**
     * Switches the system database ({@code DatabaseConfiguration}, {@code DataSource} and {@code SessionFactory})
     * over to the provided {@code target}, and then {@link #unlatch() unlatches} the system {@code DataSource} and
     * {@code SessionFactory}.
     *
     * @param target the new database to unlatch on
     */
    void unlatchTo(@Nonnull DatabaseHandle target);
}
