Imports System.Data.SqlClient

Public Class frmMain

    Dim sqlConnection As New SqlConnection
    Dim sqlCommand As New SqlCommand
    Dim strConnectionStringPrincipal As String = ""
    Dim strConnectionStringMirror As String = ""
    Dim strConnectionStringWitness As String = ""
    Dim strPrincipalName As String = ""
    Dim strMirrorName As String = ""
    Dim strWitnessName As String = ""
    Dim strDatabaseName As String = ""
    Dim strBackupRestorePath As String = ""
    Dim iPubsCounter As Integer = 9901

    Private Sub btnSelectDB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSelectDB.Click
        'wyświetlenie listy baz danych na serwerze głównym
        'uruchomienie Select Database Form
        Me.Hide()
        frmSelectDB.Show()

    End Sub

    Private Sub btnSetup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSetup.Click
        'próba zainicjowania rozwiązania z danymi podanymi przez użytkownika
        'aplikacja sporządzi kopię bezpieczeństwa w głównym katalogu C:/ i odtworzy bazę danych do katalogu głównego C:/

        'ustawienie kursora, aby użytkownik widział, że aplikacja pracuje
        Me.Cursor = System.Windows.Forms.Cursors.WaitCursor

        'połączenie z serwerem głównym i upewnienie się, że serwer jest w trybie Full Recovery


        Dim boolError As Boolean = False
        Dim strSQL As String = ""
        strDatabaseName = lblDatabaseName.Text()
        strPrincipalName = txtPrincipalServer.Text()
        strMirrorName = txtMirrorServer.Text()
        strWitnessName = txtWitnessServer.Text()
        strBackupRestorePath = txtBackupRestorePath.Text()

        'utworzenie ciągu połączenia
        strConnectionStringPrincipal = "Initial Catalog = " & strDatabaseName & _
            ";Data Source = " & strPrincipalName & ";Trusted_Connection=Yes;"

        'próba ustawienia trybu pełnego odtworzenia
        strSQL = "ALTER DATABASE [" & strDatabaseName & "] SET RECOVERY FULL;"
        boolError = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie włączania trybu pełnego odtwarzania na serwerze głównym. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Ustawiono tryb pełnego odtworzenia.")
        End If

        'utworzenie kopii bezpieczeństwa bazy
        strSQL = "BACKUP DATABASE [" & strDatabaseName & "] TO  DISK = N'" & strBackupRestorePath & _
            strDatabaseName & ".bak' WITH NOFORMAT, INIT,  NAME = N'" & strDatabaseName & _
            "-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10"
        boolError = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie tworzenia kopii bezpieczeństaw głównej bazy danych. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Utworzono kopię bezpieczeństwa bazy " & strDatabaseName)
        End If

        'odtworzenie bazy na serwerze lustrzanym
        strConnectionStringMirror = "Initial Catalog = Master" & _
            ";Data Source = " & strMirrorName & ";Trusted_Connection=Yes;"

        strSQL = "RESTORE DATABASE [" & strDatabaseName & "] FROM  DISK = N'" & strBackupRestorePath & _
            strDatabaseName & ".bak' WITH  FILE = 1, MOVE N'" & _
            strDatabaseName & "' TO N'" & strBackupRestorePath & strDatabaseName & ".mdf',  MOVE N'" & _
            strDatabaseName & "_log' TO N'C:\" & strDatabaseName & ".ldf',  " & _
            "NORECOVERY,  NOUNLOAD, REPLACE, STATS = 10"
        boolError = ExecuteNonQuery(strConnectionStringMirror, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie odtwarzania bazy lustrzanej. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Baza danych " & strDatabaseName & " odtworzona na serwerze lustrzanym.")
        End If

        'utworzenie węzłów końcowych; najpierw na serwerze głównym

        'sprawdzenie, czy węzeł główny już istnieje; jeśli tak, usunięcie węzła,
        'ponieważ na serwerze może być tylko jeden węzeł dla mechanizmu kopii lustrzanych
        strSQL = "SELECT name from sys.endpoints WHERE name = 'MirroringPrincipalSampleEndPoint'"

        Dim strReturnValue As String = CStr(ExecuteScalar(strConnectionStringPrincipal, strSQL))
        If strReturnValue = "MirroringPrincipalSampleEndPoint" Then
            'usunięcie węzła, jeśli istnieje
            strSQL = "DROP ENDPOINT MirroringPrincipalSampleEndPoint"
            boolError = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
            If (boolError) Then
                MsgBox("Błąd w trakcie usuwania węzła końcowego na serwerze głównym. Przerwanie inicjacji.")
                SetCursorBack()
                Exit Sub
            End If
        End If


        Dim strPrincipalPort As String = RetrievePortNumber(txtPrincipalEndPoint.Text)

        strSQL = "CREATE ENDPOINT [MirroringPrincipalSampleEndPoint] STATE = STARTED" & _
            " AS TCP (LISTENER_PORT = " & strPrincipalPort & ", LISTENER_IP = ALL," & _
            " RESTRICT_IP=NONE) FOR DATABASE_MIRRORING (ROLE = PARTNER," & _
            " ENCRYPTION = DISABLED)"

        'utworzenie węzła końcowego
        boolError = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie tworzenia węzła końcowego na serwerze głównym. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Utworzono węzeł końcowy na serwerze głównym.")
        End If

        'utworzenie węzła końcowego serwera kopii lustrzanej
        'jeśli istnieje - usunięcie węzła
        strSQL = "SELECT name from sys.endpoints WHERE name = 'MirroringMirrorSampleEndPoint'"

        strReturnValue = CStr(ExecuteScalar(strConnectionStringMirror, strSQL))
        If strReturnValue = "MirroringMirrorSampleEndPoint" Then
            'usunięcie węzła, jeśli istnieje
            strSQL = "DROP ENDPOINT MirroringMirrorSampleEndPoint"
            boolError = ExecuteNonQuery(strConnectionStringMirror, strSQL)
            If (boolError) Then
                MsgBox("Błąd w trakcie usuwania węzła końcowego na serwerze lustrzanym. Przerwanie inicjacji.")
                SetCursorBack()
                Exit Sub
            End If
        End If


        Dim strMirrorPort As String = RetrievePortNumber(txtMirrorEndPoint.Text)

        strSQL = "CREATE ENDPOINT [MirroringMirrorSampleEndPoint] STATE = STARTED" & _
            " AS TCP (LISTENER_PORT = " & strMirrorPort & ", LISTENER_IP = ALL," & _
            " RESTRICT_IP=NONE) FOR DATABASE_MIRRORING (ROLE = PARTNER," & _
            " ENCRYPTION = DISABLED)"

        'utworzenie węzła końcowego
        boolError = ExecuteNonQuery(strConnectionStringMirror, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie tworzenia węzła końcowego na serwerze lustrzanym. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Utworzono węzeł końcowy na serwerze lustrzanym.")
        End If


        strConnectionStringWitness = "Initial Catalog = Master" & _
            ";Data Source = " & strWitnessName & ";Trusted_Connection=Yes;"

        'sprawdzenie, czy ma być używany serwer nadzorujący
        If checkWitness.Checked = True Then

            'utworzenie węzła końcowego serwera nadzorującego
            'jeśli istnieje - usunięcie
            strSQL = "SELECT name from sys.endpoints WHERE name = 'MirroringWitnessSampleEndPoint'"

            strReturnValue = CStr(ExecuteScalar(strConnectionStringWitness, strSQL))
            If strReturnValue = "MirroringWitnessSampleEndPoint" Then
                'usunięcie węzła, jeśli istnieje
                strSQL = "DROP ENDPOINT MirroringWitnessSampleEndPoint"
                boolError = ExecuteNonQuery(strConnectionStringWitness, strSQL)
                If (boolError) Then
                    MsgBox("Błąd w trakcie usuwania węzła końcowego na serwerze nadzorującym. Przerwanie inicjacji.")
                    SetCursorBack()
                    Exit Sub
                End If
            End If


            Dim strWitnessPort As String = RetrievePortNumber(txtWitnessEndPoint.Text)

            strSQL = "CREATE ENDPOINT [MirroringWitnessSampleEndPoint] STATE = STARTED" & _
                " AS TCP (LISTENER_PORT = " & strWitnessPort & ", LISTENER_IP = ALL," & _
                " RESTRICT_IP=NONE) FOR DATABASE_MIRRORING (ROLE = WITNESS," & _
                " ENCRYPTION = DISABLED)"

            'utworzenie węzła końcowego
            boolError = ExecuteNonQuery(strConnectionStringWitness, strSQL)
            If (boolError) Then
                MsgBox("Błąd w trakcie tworzenia węzła końcowego na serwerze nadzorującym. Przerwanie inicjacji.")
                SetCursorBack()
                Exit Sub
            Else
                MsgBox("Udało się! Utworzono węzeł końcowy na serwerze nadzorującym.")
            End If

        End If

        'ustawienie partnera lustrzanej bazy danych
        strSQL = "ALTER DATABASE " & strDatabaseName & " SET PARTNER = '" & txtPrincipalEndPoint.Text & "'"

        boolError = ExecuteNonQuery(strConnectionStringMirror, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie ustawiania partnera na serwerze lustrzanym. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Ustawiono partnera na serwerze lustrzanym.")
        End If


        'ustawienie partnera głównej bazy danych
        strSQL = "ALTER DATABASE " & strDatabaseName & " SET PARTNER = '" & txtMirrorEndPoint.Text & "'"

        boolError = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie ustawiania partnera dla serwera głównego. Przerwanie inicjacji.")
            SetCursorBack()
            Exit Sub
        Else
            MsgBox("Udało się! Ustawiono partnera na serwerze głównym.")
        End If


        'sprawdzenie, czy używany jest serwer nadzorujący
        If checkWitness.Checked = True Then
            'Set Witness
            strSQL = "ALTER DATABASE " & strDatabaseName & " SET WITNESS = '" & txtWitnessEndPoint.Text & "'"

            boolError = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
            If (boolError) Then
                MsgBox("Błąd w trakcie ustawiania serwera nadzorującego na serwerze głównym. Przerwanie inicjacji.")
                SetCursorBack()
                Exit Sub
            Else
                MsgBox("Udało się! Ustawiono serwer nadzorujący na serwerze głównym.")
            End If


        End If


        'ustawienie interwału czasowego i włączenie licznika czasu
        timerMirroring.Interval = Int(listInterval.SelectedItem) * 1000
        timerMirroring.Enabled = True

        'włączenie przycisków Przywróć! i Wyłącz
        btnFail.Enabled = True
        btnTurnOff.Enabled = True

        SetCursorBack()
    End Sub
    Private Function RetrievePortNumber(ByVal strTCPAddress As String) As String
        'odczytanie portu z ciągu węzła końcowego
        Dim iColon As Integer = InStr(strTCPAddress, ":")
        'pierwszy średnik, przejście do drugiego
        iColon = InStr(iColon + 1, strTCPAddress, ":")


        'odczytanie wszystkiego na prawo od średnika
        RetrievePortNumber = Mid(strTCPAddress, iColon + 1)

    End Function
    Private Sub SetCursorBack()
        Me.Cursor = System.Windows.Forms.Cursors.Default
    End Sub
    Private Function ExecuteNonQuery(ByVal strConnectString As String, ByVal strSQLCommand As String) As Boolean
        Dim strSQL As String = ""
        Dim sqlConnection As New SqlConnection(strConnectString)

        Try
            With sqlConnection
                .Open()
                Dim sqlCommand As New SqlCommand(strSQLCommand, sqlConnection)
                sqlCommand.ExecuteNonQuery()
                'zamknięcie połączenia
                .Close()
                ExecuteNonQuery = False
            End With

        Catch
            MsgBox("Błąd!  Błąd#" & Err.Number & " Opis: " & Err.Description)
            'zamknięcie połączenia
            sqlConnection.Close()
            ExecuteNonQuery = True
        End Try

    End Function
    Private Function ExecuteNonQueryForMirror(ByVal strConnectString As String, ByVal strSQLCommand As String) As Boolean
        'wykonanie zapytania po ustanowieniu mechanizmu kopii lustrzanej

        Dim strSQL As String = ""
        Dim sqlConnection As New SqlConnection(strConnectString)

        Try
            With sqlConnection
                .Open()
                'wypisanie źródła danych dla połączenia, aby sprawdzić,
                'czy komunikujemy się z serwerem głównym, czy lustrzanym
                lblConnectedServerText.Text = sqlConnection.DataSource()

                Dim sqlCommand As New SqlCommand(strSQLCommand, sqlConnection)
                sqlCommand.ExecuteNonQuery()


                'zamknięcie połączenia
                .Close()
                ExecuteNonQueryForMirror = False
            End With

        Catch
            MsgBox("Błąd!  Błąd#" & Err.Number & " Opis: " & Err.Description)
            'zamknięcie połączenia
            sqlConnection.Close()
            ExecuteNonQueryForMirror = True
        End Try

    End Function
    Private Function ExecuteScalar(ByVal strConnectString As String, ByVal strSQLCommand As String) As Object
        Dim strSQL As String = ""
        Dim sqlConnection As New SqlConnection(strConnectString)

        Try
            With sqlConnection
                .Open()
                Dim sqlCommand As New SqlCommand(strSQLCommand, sqlConnection)
                Dim oReturnValue As Object = sqlCommand.ExecuteScalar()
                'zamknięcie połączenia
                .Close()
                If IsDBNull(oReturnValue) Then
                    oReturnValue = ""
                End If
                ExecuteScalar = oReturnValue
            End With

        Catch
            MsgBox("Błąd!  Błąd#" & Err.Number & " Opis: " & Err.Description)
            'zamknięcie połączenia
            sqlConnection.Close()
            ExecuteScalar = True
        End Try

    End Function
    Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'DO USUNIĘCIA!
        txtPrincipalServer.Text = "thomrizwinxp6"
        txtMirrorServer.Text = "thomrizwinxp6\server2"
        txtWitnessServer.Text = "thomrizwinxp6\server3"

        txtPrincipalEndPoint.Text = "TCP://thomrizwinxp6.redmond.corp.microsoft.com:6000"
        txtMirrorEndPoint.Text = "TCP://thomrizwinxp6.redmond.corp.microsoft.com:6001"
        txtWitnessEndPoint.Text = "TCP://thomrizwinxp6.redmond.corp.microsoft.com:6002"
        txtBackupRestorePath.Text = "C:\"

        listInterval.SelectedItem = "5"
    End Sub

    Private Sub timerMirroring_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles timerMirroring.Tick
        SetDBMirrorStatusandPrincipal()
        InsertDataIntoDatabase()

    End Sub
    Private Sub InsertDataIntoDatabase()
        Dim strSQL As String = ""
        Dim boolError As Boolean = False

        strConnectionStringPrincipal = "Initial Catalog = " & strDatabaseName & _
            ";Data Source = " & strPrincipalName & ";Trusted_Connection=Yes;"

        If UCase(strDatabaseName) = "PUBS" Then
            'wstawienie danych do pubs
            'zwiększenie licznika
            iPubsCounter += 1
            strSQL = "INSERT INTO [publishers] (pub_id, pub_name, city, state, country)" & _
                " VALUES ('" & CStr(iPubsCounter) & "','Test','Test','WA','Test')"

            boolError = ExecuteNonQueryForMirror(strConnectionStringPrincipal, strSQL)
            If (boolError) Then
                lblDataFlowText.Text = "Błąd w trakcie wstawiania danych."
            Else
                lblDataFlowText.Text = "Dodano wydawcę #" & iPubsCounter
            End If

        End If
    End Sub
    Private Sub SetDBMirrorStatusandPrincipal()
        'odczytanie z serwera głównego statusu kopii lustrzanej
        Dim strReturnValue As String = ""
        Dim strSQL As String = ""

        strConnectionStringPrincipal = "Initial Catalog = Master" & _
           ";Data Source = " & strPrincipalName & ";Trusted_Connection=Yes;"


        'najpierw opis stanu
        strSQL = "SELECT mirroring_state_desc from sys.databases WHERE name = '" & strDatabaseName & "'"

        strReturnValue = ExecuteScalar(strConnectionStringPrincipal, strSQL)
        If strReturnValue = "" Then
            strReturnValue = "Nieskonfigurowane"
        End If
        lblDBMirrorStatusText.Text = strReturnValue


        'odczytanie roli serwera głównego
        strSQL = "SELECT mirroring_role_desc from sys.databases WHERE name = '" & strDatabaseName & "'"

        strReturnValue = ExecuteScalar(strConnectionStringPrincipal, strSQL)
        If strReturnValue = "" Then
            strReturnValue = "Nieskonfigurowane"
        End If

        lblPrincipalText.Text = strReturnValue

    End Sub
    Private Sub btnTurnOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTurnOff.Click
        Dim boolError As Boolean = False
        Dim strSQL As String = ""
        Dim boolError2 As Boolean = False

        If strMirrorName = "" Then
            'ustawienie nazwy serwera lustrzanego
            strMirrorName = txtMirrorServer.Text()
        End If

        If strDatabaseName = "" Then
            MsgBox("Proszę najpierw wybrać bazę danych.")
            Exit Sub
        End If

        'zablokowanie czasomierza
        timerMirroring.Enabled = False


        'usunięcie nowych rekordów z pubs
        strConnectionStringPrincipal = "Initial Catalog = " & strDatabaseName & _
            ";Data Source = " & strPrincipalName & ";Trusted_Connection=Yes;"

        strSQL = "SELECT mirroring_role_desc FROM sys.databases WHERE name = '" & strDatabaseName & "'"
        Dim strRole As String = ExecuteScalar(strConnectionStringPrincipal, strSQL)
        strSQL = "DELETE FROM publishers WHERE pub_name = 'Test'"

        If (boolError) Then
            'coś się stało, trzeba przełączyć
            'próba przywrócenia działania na serwerze lustrzanym
            boolError2 = ExecuteNonQuery(strConnectionStringMirror, strSQL)
        Else
            If UCase(strRole) = "PRINCIPAL" Then
                boolError2 = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
            Else
                boolError2 = ExecuteNonQuery(strConnectionStringMirror, strSQL)
            End If
        End If

        If (boolError2) Then
            MsgBox("Błąd w trakcie usuwania nowych rekordów z bazy pubs.")
        Else
            MsgBox("Udało się usunąć nowe rekordy z bazy pubs.")
        End If


        'wyłączenie mechanizmu
        strConnectionStringMirror = "Initial Catalog = Master" & _
           ";Data Source = " & strMirrorName & ";Trusted_Connection=Yes;"

        strSQL = "ALTER DATABASE [" & strDatabaseName & "] SET PARTNER OFF"

        'komunikacja z serwerem lustrzanym na wypadek, gdyby został przełączony do serwera głównego
        boolError = ExecuteNonQuery(strConnectionStringMirror, strSQL)
        If (boolError) Then
            MsgBox("Błąd w trakcie wyłączania mechanizmu.  Wyjście.")
            Exit Sub
        Else
            MsgBox("Udało się! Wyłączono mechanizm.")
            lblDBMirrorStatusText.Text = "Nieskonfigurowane"
            lblConnectedServerText.Text = "Nieskonfigurowane"
            lblPrincipalText.Text = "Nieskonfigurowane"
        End If




    End Sub
    Friend Sub SetDatabaseName()
        strDatabaseName = lblDatabaseName.Text()
    End Sub

    Private Sub btnFail_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFail.Click
        'przywrócenie działania na serwerze lustrzanym przez ustalenie aktualnego serwera głównego
        'połączenie z serwerem głównym i sprawdzenie, czy nadal pełni tę rolę
        Dim strSQL As String = ""
        Dim boolError As Boolean = False
        Dim boolError2 As Boolean = False

        strConnectionStringPrincipal = "Initial Catalog = Master" & _
            ";Data Source = " & strPrincipalName & ";Trusted_Connection=Yes;"



        strSQL = "SELECT mirroring_role_desc FROM sys.databases WHERE name = '" & strDatabaseName & "'"
        Dim strRole As String = ExecuteScalar(strConnectionStringPrincipal, strSQL)
        strSQL = "ALTER DATABASE [" & strDatabaseName & "] SET PARTNER FAILOVER"

        If (boolError) Then
            'coś się stało, trzeba przełączyć
            'próba przywrócenia działania na serwerze lustrzanym
            boolError2 = ExecuteNonQuery(strConnectionStringMirror, strSQL)
        Else
            If UCase(strRole) = "PRINCIPAL" Then
                boolError2 = ExecuteNonQuery(strConnectionStringPrincipal, strSQL)
            Else
                boolError2 = ExecuteNonQuery(strConnectionStringMirror, strSQL)
            End If
        End If

    End Sub

    
    Private Sub lblDatabaseName_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lblDatabaseName.TextChanged
        If lblDatabaseName.Text <> "" Then
            'udostępnienie przycisku Skonfiguruj
            btnSetup.Enabled = True
        End If
    End Sub
End Class
