424 lines
16 KiB
C#
424 lines
16 KiB
C#
|
using System;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.IO;
|
|||
|
|
|||
|
namespace SafeMobileLib
|
|||
|
{
|
|||
|
public static class DBInteraction
|
|||
|
{
|
|||
|
|
|||
|
public static string safemobilePath = Utils.GetRegValue("Path", "SafeMobile");
|
|||
|
|
|||
|
|
|||
|
public static string SafeMobilePath
|
|||
|
{
|
|||
|
get { return safemobilePath; }
|
|||
|
set { safemobilePath = value; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="connStr">”host = 10.120.1.130 port = 5432 user = postgres dbname = safedispatchdb”</param>
|
|||
|
public static bool RewindCommand(string connStr)
|
|||
|
{
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
string dbPath = safemobilePath + "\\postgresql\\SafeDB";
|
|||
|
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine($"pg_rewind.exe –-target-pgdata= {dbPath} –-source-server= {connStr}");
|
|||
|
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
|
|||
|
}
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
|
|||
|
if (output.Contains("Done!"))
|
|||
|
{
|
|||
|
Utils.WriteLine("RewindCommand: " + output, ConsoleColor.Magenta);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public static void ReceiveXlogCommand(string archive_folder, string slot_name, string connStr)
|
|||
|
{
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine($"pg_receivexlog.exe –-D {archive_folder} -v --slot= {slot_name} -d= {connStr} ");
|
|||
|
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
|
|||
|
}
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
|
|||
|
Utils.WriteLine("ReceiveXlogCommand: " + output, ConsoleColor.Magenta);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public static void BaseBackup(string masterIP)
|
|||
|
{
|
|||
|
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
string extractPath = $"{safemobilePath}\\postgresql\\pgsql\\bin\\SafeDBMaster";
|
|||
|
string SafeDbFolder = $"{safemobilePath}\\postgresql\\SafeDB";
|
|||
|
|
|||
|
if (Directory.Exists(extractPath))
|
|||
|
Directory.Delete(extractPath, true);
|
|||
|
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine($"pg_basebackup.exe -X stream -P -h {masterIP} -U postgres -D SafeDBMaster");
|
|||
|
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
|
|||
|
}
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
|
|||
|
Utils.WriteLine("BaseBackup completed: " + output, ConsoleColor.Magenta);
|
|||
|
}
|
|||
|
|
|||
|
// Get our files (recursive and any of them, based on the 2nd param of the Directory.GetFiles() method
|
|||
|
string[] originalFiles = Directory.GetFiles(extractPath, "*", SearchOption.AllDirectories);
|
|||
|
|
|||
|
// Dealing with a string array, so let's use the actionable Array.ForEach() with a anonymous method
|
|||
|
Array.ForEach(originalFiles, (originalFileLocation) =>
|
|||
|
{
|
|||
|
// Get the FileInfo for both of our files
|
|||
|
FileInfo originalFile = new FileInfo(originalFileLocation);
|
|||
|
FileInfo destFile = new FileInfo(originalFileLocation.Replace(extractPath, SafeDbFolder));
|
|||
|
// ^^ We can fill the FileInfo() constructor with files that don't exist...
|
|||
|
|
|||
|
// ... because we check it here
|
|||
|
if (destFile.Exists)
|
|||
|
{
|
|||
|
|
|||
|
originalFile.CopyTo(destFile.FullName, true);
|
|||
|
|
|||
|
}
|
|||
|
else // ... otherwise create any missing directories and copy the folder over
|
|||
|
{
|
|||
|
Directory.CreateDirectory(destFile.DirectoryName); // Does nothing on directories that already exist
|
|||
|
originalFile.CopyTo(destFile.FullName, true); // Copy but don't over-write
|
|||
|
}
|
|||
|
|
|||
|
});
|
|||
|
Utils.WriteLine("SafeDB folder was successfully updated!!! " + SafeDbFolder, ConsoleColor.DarkGreen);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Replication slot ERROR: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a replication Slot in the database
|
|||
|
/// </summary>
|
|||
|
public static void CreateReplicationSlot()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Utils.WriteLine("Creating Replication Slot");
|
|||
|
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine("psql.exe -U postgres");
|
|||
|
sw.WriteLine("SELECT * FROM pg_create_physical_replication_slot('replication_slot_node');");
|
|||
|
sw.WriteLine("SELECT * FROM pg_replication_slots;");
|
|||
|
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
}
|
|||
|
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
Utils.WriteLine("Replication Slot Created " + output, ConsoleColor.Magenta);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Replication slot ERROR: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void DropReplicationSlot()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Utils.WriteLine("Dropping Replication Slot");
|
|||
|
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine("psql.exe -U postgres");
|
|||
|
sw.WriteLine("select pg_drop_replication_slot('replication_slot_node');");
|
|||
|
sw.WriteLine("SELECT * FROM pg_replication_slots;");
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
Utils.WriteLine("Replication Slot Deleted!!!! " + output, ConsoleColor.Magenta);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Replication slot ERROR: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static bool CheckExistingReplicationSlot()
|
|||
|
{
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine("psql.exe -U postgres");
|
|||
|
sw.WriteLine("SELECT * FROM pg_replication_slots;");
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
}
|
|||
|
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
//Utils.WriteLine("Replication Slot Created " + output, ConsoleColor.Magenta);
|
|||
|
if (output.Contains("replication_slot_node") == false)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Existing Replication slot ERROR: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
public static bool CheckReplicationIsActive()
|
|||
|
{
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine("psql.exe -U postgres");
|
|||
|
sw.WriteLine("SELECT * FROM pg_replication_slots;");
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
}
|
|||
|
|
|||
|
using (StreamReader reader = process.StandardOutput)
|
|||
|
{
|
|||
|
string output = reader.ReadToEnd();
|
|||
|
process.WaitForExit();
|
|||
|
if (output.Contains(" | t |") == false)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Replication slot ERROR: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void CheckDelay()
|
|||
|
{
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
Process process = new Process();
|
|||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|||
|
startInfo.WindowStyle = ProcessWindowStyle.Maximized;
|
|||
|
startInfo.FileName = "cmd.exe";
|
|||
|
startInfo.Verb = "runas";
|
|||
|
startInfo.RedirectStandardInput = true;
|
|||
|
startInfo.RedirectStandardOutput = true;
|
|||
|
startInfo.UseShellExecute = false;
|
|||
|
process.StartInfo = startInfo;
|
|||
|
process.Start();
|
|||
|
|
|||
|
using (StreamWriter sw = process.StandardInput)
|
|||
|
{
|
|||
|
if (sw.BaseStream.CanWrite)
|
|||
|
{
|
|||
|
string appPath = safemobilePath + "\\postgresql\\pgsql\\bin";
|
|||
|
sw.WriteLine("pushd " + appPath);
|
|||
|
sw.WriteLine("psql.exe -U postgres");
|
|||
|
sw.WriteLine("select case when pg_last_xlog_receive_location() = pg_last_xlog_replay_location() then 0 else extract (epoch from now() - pg_last_xact_replay_timestamp()) end as log_delay;");
|
|||
|
}
|
|||
|
sw.Close();
|
|||
|
}
|
|||
|
|
|||
|
using (StreamReader file = process.StandardOutput)
|
|||
|
{
|
|||
|
int counter = 0;
|
|||
|
bool writeNextLine = false;
|
|||
|
string line;
|
|||
|
|
|||
|
// Read the file and display it line by line.
|
|||
|
while ((line = file.ReadLine()) != null)
|
|||
|
{
|
|||
|
if (writeNextLine)
|
|||
|
{
|
|||
|
Utils.WriteLine(line.Trim().ToString() + " seconds delay from Master server");
|
|||
|
}
|
|||
|
writeNextLine = line.Contains("-----------");
|
|||
|
counter++;
|
|||
|
}
|
|||
|
file.Close();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Check Delay ERROR: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|