diff --git a/Makefile b/Makefile
index 9880e5db..eb3e3ee2 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ OBJS = src/backup.o src/catalog.o src/configure.o src/data.o \
src/util.o src/validate.o src/datapagemap.o src/parsexlog.o \
src/xlogreader.o src/streamutil.o src/receivelog.o \
src/archive.o src/utils/parray.o src/utils/pgut.o src/utils/logger.o \
- src/utils/json.o
+ src/utils/json.o src/utils/thread.o
EXTRA_CLEAN = src/datapagemap.c src/datapagemap.h src/xlogreader.c \
src/receivelog.c src/receivelog.h src/streamutil.c src/streamutil.h src/logging.h
@@ -63,6 +63,7 @@ src/streamutil.c: $(top_srcdir)/src/bin/pg_basebackup/streamutil.c
src/streamutil.h: $(top_srcdir)/src/bin/pg_basebackup/streamutil.h
rm -f $@ && $(LN_S) $(srchome)/src/bin/pg_basebackup/streamutil.h $@
+
ifeq ($(MAJORVERSION),10)
src/walmethods.c: $(top_srcdir)/src/bin/pg_basebackup/walmethods.c
rm -f $@ && $(LN_S) $(srchome)/src/bin/pg_basebackup/walmethods.c $@
diff --git a/doit.cmd b/doit.cmd
new file mode 100644
index 00000000..cc29bc88
--- /dev/null
+++ b/doit.cmd
@@ -0,0 +1 @@
+perl win32build.pl "C:\Program Files\PostgresProEnterprise\10" "C:\projects\pgwininstall2\pgwininstall\builddir\postgresql\postgresql-10.3\src"
\ No newline at end of file
diff --git a/doit96.cmd b/doit96.cmd
new file mode 100644
index 00000000..94d242c9
--- /dev/null
+++ b/doit96.cmd
@@ -0,0 +1 @@
+perl win32build96.pl "C:\PgPro96" "C:\PgProject\pg96ee\postgrespro\src"
\ No newline at end of file
diff --git a/msvs/pg_probackup.sln b/msvs/pg_probackup.sln
new file mode 100644
index 00000000..2df4b404
--- /dev/null
+++ b/msvs/pg_probackup.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2013 for Windows Desktop
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pg_probackup", "pg_probackup.vcxproj", "{4886B21A-D8CA-4A03-BADF-743B24C88327}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Debug|Win32.Build.0 = Debug|Win32
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Debug|x64.ActiveCfg = Debug|x64
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Debug|x64.Build.0 = Debug|x64
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Release|Win32.ActiveCfg = Release|Win32
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Release|Win32.Build.0 = Release|Win32
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Release|x64.ActiveCfg = Release|x64
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/msvs/template.pg_probackup.vcxproj b/msvs/template.pg_probackup.vcxproj
new file mode 100644
index 00000000..044a3e73
--- /dev/null
+++ b/msvs/template.pg_probackup.vcxproj
@@ -0,0 +1,209 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}
+ Win32Proj
+ pg_probackup
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+ true
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+ false
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+ false
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ @ADDLIBS32@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ @ADDLIBS32@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+ %(AdditionalLibraryDirectories)
+ libc;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+ %(AdditionalLibraryDirectories)
+ libc;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/msvs/template.pg_probackup96.vcxproj b/msvs/template.pg_probackup96.vcxproj
new file mode 100644
index 00000000..c095d7cc
--- /dev/null
+++ b/msvs/template.pg_probackup96.vcxproj
@@ -0,0 +1,207 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}
+ Win32Proj
+ pg_probackup
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+ true
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+ false
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+ false
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;@PGSRC@;$(IncludePath)
+ @PGROOT@\lib;$(LibraryPath)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ @ADDLIBS32@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ @ADDLIBS32@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+ %(AdditionalLibraryDirectories)
+ libc;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+ %(AdditionalLibraryDirectories)
+ libc;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/msvs/template.pg_probackup_2.vcxproj b/msvs/template.pg_probackup_2.vcxproj
new file mode 100644
index 00000000..2fc101a4
--- /dev/null
+++ b/msvs/template.pg_probackup_2.vcxproj
@@ -0,0 +1,203 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {4886B21A-D8CA-4A03-BADF-743B24C88327}
+ Win32Proj
+ pg_probackup
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;$(IncludePath)
+ @PGROOT@\lib;@$(LibraryPath)
+
+
+ true
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;$(IncludePath)
+ @PGROOT@\lib;@$(LibraryPath)
+
+
+ false
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;$(IncludePath)
+ @PGROOT@\lib;@$(LibraryPath)
+
+
+ false
+ ../;@PGSRC@\include;@PGSRC@\bin\pg_basebackup;@PGSRC@\bin\pg_rewind;@PGSRC@\include\port\win32_msvc;@PGSRC@\interfaces\libpq;@PGSRC@\include\port\win32;@PGSRC@\port;@ADDINCLUDE@;$(IncludePath)
+ @PGROOT@\lib;@$(LibraryPath)
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+ libc;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+ @ADDLIBS@;libpgfeutils.lib;libpgcommon.lib;libpgport.lib;libpq.lib;ws2_32.lib;%(AdditionalDependencies)
+ libc;%(IgnoreSpecificDefaultLibraries)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/backup.c b/src/backup.c
index 5b4063fa..f24a0b0f 100644
--- a/src/backup.c
+++ b/src/backup.c
@@ -18,16 +18,16 @@
#include
#include
#include
-#include
-#include "libpq/pqsignal.h"
-#include "storage/bufpage.h"
#include "catalog/catalog.h"
#include "catalog/pg_tablespace.h"
#include "datapagemap.h"
-#include "receivelog.h"
-#include "streamutil.h"
+#include "libpq/pqsignal.h"
#include "pgtar.h"
+#include "receivelog.h"
+#include "storage/bufpage.h"
+#include "streamutil.h"
+#include "utils/thread.h"
static int standby_message_timeout = 10 * 1000; /* 10 sec = default */
static XLogRecPtr stop_backup_lsn = InvalidXLogRecPtr;
@@ -89,8 +89,8 @@ static bool pg_stop_backup_is_sent = false;
static void backup_cleanup(bool fatal, void *userdata);
static void backup_disconnect(bool fatal, void *userdata);
-static void backup_files(void *arg);
-static void remote_backup_files(void *arg);
+static void *backup_files(void *arg);
+static void *remote_backup_files(void *arg);
static void do_backup_instance(void);
@@ -253,7 +253,11 @@ ReceiveFileList(parray* files, PGconn *conn, PGresult *res, int rownum)
else if (copybuf[156] == '2')
{
/* Symlink */
+#ifndef WIN32
pgfile->mode |= S_IFLNK;
+#else
+ pgfile->mode |= S_IFDIR;
+#endif
}
else
elog(ERROR, "Unrecognized link indicator \"%c\"\n",
@@ -289,7 +293,7 @@ remote_copy_file(PGconn *conn, pgFile* file)
DATABASE_DIR);
join_path_components(to_path, database_path, file->path);
- out = fopen(to_path, "w");
+ out = fopen(to_path, PG_BINARY_W);
if (out == NULL)
{
int errno_tmp = errno;
@@ -363,7 +367,7 @@ remote_copy_file(PGconn *conn, pgFile* file)
* Take a remote backup of the PGDATA at a file level.
* Copy all directories and files listed in backup_files_list.
*/
-static void
+static void *
remote_backup_files(void *arg)
{
int i;
@@ -385,7 +389,7 @@ remote_backup_files(void *arg)
if (S_ISDIR(file->mode))
continue;
- if (__sync_lock_test_and_set(&file->lock, 1) != 0)
+ if (!pg_atomic_test_set_flag(&file->lock))
continue;
file_backup_conn = pgut_connect_replication(pgut_dbname);
@@ -441,6 +445,8 @@ remote_backup_files(void *arg)
/* Data files transferring is successful */
arguments->ret = 0;
+
+ return NULL;
}
/*
@@ -456,8 +462,9 @@ do_backup_instance(void)
char label[1024];
XLogRecPtr prev_backup_start_lsn = InvalidXLogRecPtr;
- pthread_t backup_threads[num_threads];
- backup_files_args *backup_threads_args[num_threads];
+ /* arrays with meta info for multi threaded backup */
+ pthread_t *backup_threads;
+ backup_files_args *backup_threads_args;
bool backup_isok = true;
pgBackup *prev_backup = NULL;
@@ -681,16 +688,19 @@ do_backup_instance(void)
}
/* setup threads */
- __sync_lock_release(&file->lock);
+ pg_atomic_clear_flag(&file->lock);
}
/* sort by size for load balancing */
parray_qsort(backup_files_list, pgFileCompareSize);
/* init thread args with own file lists */
+ backup_threads = (pthread_t *) palloc(sizeof(pthread_t)*num_threads);
+ backup_threads_args = (backup_files_args *) palloc(sizeof(backup_files_args)*num_threads);
+
for (i = 0; i < num_threads; i++)
{
- backup_files_args *arg = pg_malloc(sizeof(backup_files_args));
+ backup_files_args *arg = &(backup_threads_args[i]);
arg->from_root = pgdata;
arg->to_root = database_path;
@@ -701,33 +711,27 @@ do_backup_instance(void)
arg->thread_cancel_conn = NULL;
/* By default there are some error */
arg->ret = 1;
- backup_threads_args[i] = arg;
}
/* Run threads */
elog(LOG, "Start transfering data files");
for (i = 0; i < num_threads; i++)
{
+ backup_files_args *arg = &(backup_threads_args[i]);
elog(VERBOSE, "Start thread num: %i", i);
if (!is_remote_backup)
- pthread_create(&backup_threads[i], NULL,
- (void *(*)(void *)) backup_files,
- backup_threads_args[i]);
+ pthread_create(&backup_threads[i], NULL, backup_files, arg);
else
- pthread_create(&backup_threads[i], NULL,
- (void *(*)(void *)) remote_backup_files,
- backup_threads_args[i]);
+ pthread_create(&backup_threads[i], NULL, remote_backup_files, arg);
}
-
+
/* Wait threads */
for (i = 0; i < num_threads; i++)
{
pthread_join(backup_threads[i], NULL);
- if (backup_threads_args[i]->ret == 1)
+ if (backup_threads_args[i].ret == 1)
backup_isok = false;
-
- pg_free(backup_threads_args[i]);
}
if (backup_isok)
elog(LOG, "Data files are transfered");
@@ -1017,7 +1021,7 @@ check_system_identifiers(void)
system_id_pgdata = get_system_identifier(pgdata);
system_id_conn = get_remote_system_identifier(backup_conn);
-
+
if (system_id_conn != system_identifier)
elog(ERROR, "Backup data directory was initialized for system id %ld, but connected instance system id is %ld",
system_identifier, system_id_conn);
@@ -1040,14 +1044,15 @@ confirm_block_size(const char *name, int blcksz)
res = pgut_execute(backup_conn, "SELECT pg_catalog.current_setting($1)", 1, &name);
if (PQntuples(res) != 1 || PQnfields(res) != 1)
elog(ERROR, "cannot get %s: %s", name, PQerrorMessage(backup_conn));
-
+
block_size = strtol(PQgetvalue(res, 0, 0), &endp, 10);
- PQclear(res);
-
if ((endp && *endp) || block_size != blcksz)
elog(ERROR,
"%s(%d) is not compatible(%d expected)",
name, block_size, blcksz);
+
+ PQclear(res);//bad pointer to endp
+
}
/*
@@ -1802,7 +1807,7 @@ pg_stop_backup(pgBackup *backup)
/* Write backup_label */
join_path_components(backup_label, path, PG_BACKUP_LABEL_FILE);
- fp = fopen(backup_label, "w");
+ fp = fopen(backup_label, PG_BINARY_W);
if (fp == NULL)
elog(ERROR, "can't open backup label file \"%s\": %s",
backup_label, strerror(errno));
@@ -1850,7 +1855,7 @@ pg_stop_backup(pgBackup *backup)
char tablespace_map[MAXPGPATH];
join_path_components(tablespace_map, path, PG_TABLESPACE_MAP_FILE);
- fp = fopen(tablespace_map, "w");
+ fp = fopen(tablespace_map, PG_BINARY_W);
if (fp == NULL)
elog(ERROR, "can't open tablespace map file \"%s\": %s",
tablespace_map, strerror(errno));
@@ -2006,7 +2011,7 @@ backup_disconnect(bool fatal, void *userdata)
* In incremental backup mode, copy only files or datafiles' pages changed after
* previous backup.
*/
-static void
+static void *
backup_files(void *arg)
{
int i;
@@ -2021,7 +2026,7 @@ backup_files(void *arg)
pgFile *file = (pgFile *) parray_get(arguments->backup_files_list, i);
elog(VERBOSE, "Copying file: \"%s\" ", file->path);
- if (__sync_lock_test_and_set(&file->lock, 1) != 0)
+ if (!pg_atomic_test_set_flag(&file->lock))
continue;
/* check for interrupt */
@@ -2126,6 +2131,8 @@ backup_files(void *arg)
/* Data files transferring is successful */
arguments->ret = 0;
+
+ return NULL;
}
/*
diff --git a/src/catalog.c b/src/catalog.c
index eb5d3be7..f19628c3 100644
--- a/src/catalog.c
+++ b/src/catalog.c
@@ -12,7 +12,6 @@
#include
#include
-#include
#include
#include
#include
diff --git a/src/configure.c b/src/configure.c
index dc80981a..2fc27892 100644
--- a/src/configure.c
+++ b/src/configure.c
@@ -132,7 +132,8 @@ writeBackupCatalogConfig(FILE *out, pgBackupConfig *config)
fprintf(out, "#Backup instance info\n");
fprintf(out, "PGDATA = %s\n", config->pgdata);
- fprintf(out, "system-identifier = %li\n", config->system_identifier);
+ //fprintf(out, "system-identifier = %li\n", config->system_identifier);
+ fprintf(out, "system-identifier = %" INT64_MODIFIER "u\n", config->system_identifier);
fprintf(out, "#Connection parameters:\n");
if (config->pgdatabase)
diff --git a/src/data.c b/src/data.c
index a1bdb91a..be07ce64 100644
--- a/src/data.c
+++ b/src/data.c
@@ -446,7 +446,7 @@ backup_data_file(backup_files_args* arguments,
INIT_CRC32C(file->crc);
/* open backup mode file for read */
- in = fopen(file->path, "r");
+ in = fopen(file->path, PG_BINARY_R);
if (in == NULL)
{
FIN_CRC32C(file->crc);
@@ -480,7 +480,7 @@ backup_data_file(backup_files_args* arguments,
/* open backup file for write */
join_path_components(to_path, to_root, file->path + strlen(from_root) + 1);
- out = fopen(to_path, "w");
+ out = fopen(to_path, PG_BINARY_W);
if (out == NULL)
{
int errno_tmp = errno;
@@ -569,18 +569,18 @@ restore_data_file(const char *from_root,
pgFile *file,
pgBackup *backup)
{
- char to_path[MAXPGPATH];
- FILE *in = NULL;
- FILE *out = NULL;
- BackupPageHeader header;
- BlockNumber blknum;
- size_t file_size;
+ char to_path[MAXPGPATH];
+ FILE *in = NULL;
+ FILE *out = NULL;
+ BackupPageHeader header;
+ BlockNumber blknum;
+ size_t file_size;
/* BYTES_INVALID allowed only in case of restoring file from DELTA backup */
if (file->write_size != BYTES_INVALID)
{
/* open backup mode file for read */
- in = fopen(file->path, "r");
+ in = fopen(file->path, PG_BINARY_R);
if (in == NULL)
{
elog(ERROR, "cannot open backup file \"%s\": %s", file->path,
@@ -594,9 +594,9 @@ restore_data_file(const char *from_root,
* re-open it with "w" to create an empty file.
*/
join_path_components(to_path, to_root, file->path + strlen(from_root) + 1);
- out = fopen(to_path, "r+");
+ out = fopen(to_path, PG_BINARY_R "+");
if (out == NULL && errno == ENOENT)
- out = fopen(to_path, "w");
+ out = fopen(to_path, PG_BINARY_W);
if (out == NULL)
{
int errno_tmp = errno;
@@ -690,13 +690,13 @@ restore_data_file(const char *from_root,
}
}
- /*
- * DELTA backup have no knowledge about truncated blocks as PAGE or PTRACK do
- * But during DELTA backup we read every file in PGDATA and thus DELTA backup
- * knows exact size of every file at the time of backup.
- * So when restoring file from DELTA backup we, knowning it`s size at
- * a time of a backup, can truncate file to this size.
- */
+ /*
+ * DELTA backup have no knowledge about truncated blocks as PAGE or PTRACK do
+ * But during DELTA backup we read every file in PGDATA and thus DELTA backup
+ * knows exact size of every file at the time of backup.
+ * So when restoring file from DELTA backup we, knowning it`s size at
+ * a time of a backup, can truncate file to this size.
+ */
if (backup->backup_mode == BACKUP_MODE_DIFF_DELTA)
{
@@ -759,7 +759,7 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
file->write_size = 0;
/* open backup mode file for read */
- in = fopen(file->path, "r");
+ in = fopen(file->path, PG_BINARY_R);
if (in == NULL)
{
FIN_CRC32C(crc);
@@ -775,7 +775,7 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
/* open backup file for write */
join_path_components(to_path, to_root, file->path + strlen(from_root) + 1);
- out = fopen(to_path, "w");
+ out = fopen(to_path, PG_BINARY_W);
if (out == NULL)
{
int errno_tmp = errno;
@@ -918,7 +918,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
bool overwrite)
{
FILE *in = NULL;
- FILE *out;
+ FILE *out=NULL;
char buf[XLOG_BLCKSZ];
const char *to_path_p = to_path;
char to_path_temp[MAXPGPATH];
@@ -930,7 +930,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
#endif
/* open file for read */
- in = fopen(from_path, "r");
+ in = fopen(from_path, PG_BINARY_R);
if (in == NULL)
elog(ERROR, "Cannot open source WAL file \"%s\": %s", from_path,
strerror(errno));
@@ -946,7 +946,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", gz_to_path);
- gz_out = gzopen(to_path_temp, "wb");
+ gz_out = gzopen(to_path_temp, PG_BINARY_W);
if (gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
elog(ERROR, "Cannot set compression level %d to file \"%s\": %s",
compress_level, to_path_temp, get_gz_error(gz_out, errno));
@@ -961,7 +961,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", to_path);
- out = fopen(to_path_temp, "w");
+ out = fopen(to_path_temp, PG_BINARY_W);
if (out == NULL)
elog(ERROR, "Cannot open destination WAL file \"%s\": %s",
to_path_temp, strerror(errno));
@@ -1083,7 +1083,7 @@ get_wal_file(const char *from_path, const char *to_path)
#endif
/* open file for read */
- in = fopen(from_path, "r");
+ in = fopen(from_path, PG_BINARY_R);
if (in == NULL)
{
#ifdef HAVE_LIBZ
@@ -1092,7 +1092,7 @@ get_wal_file(const char *from_path, const char *to_path)
* extension.
*/
snprintf(gz_from_path, sizeof(gz_from_path), "%s.gz", from_path);
- gz_in = gzopen(gz_from_path, "rb");
+ gz_in = gzopen(gz_from_path, PG_BINARY_R);
if (gz_in == NULL)
{
if (errno == ENOENT)
@@ -1120,7 +1120,7 @@ get_wal_file(const char *from_path, const char *to_path)
/* open backup file for write */
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", to_path);
- out = fopen(to_path_temp, "w");
+ out = fopen(to_path_temp, PG_BINARY_W);
if (out == NULL)
elog(ERROR, "Cannot open destination WAL file \"%s\": %s",
to_path_temp, strerror(errno));
@@ -1254,7 +1254,7 @@ calc_file_checksum(pgFile *file)
file->write_size = 0;
/* open backup mode file for read */
- in = fopen(file->path, "r");
+ in = fopen(file->path, PG_BINARY_R);
if (in == NULL)
{
FIN_CRC32C(crc);
diff --git a/src/dir.c b/src/dir.c
index 8df3da3f..20725f88 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -10,7 +10,6 @@
#include "pg_probackup.h"
-#include
#include
#include
#include
@@ -102,10 +101,12 @@ int
dir_create_dir(const char *dir, mode_t mode)
{
char copy[MAXPGPATH];
- char parent[MAXPGPATH];
+ char *parent;
strncpy(copy, dir, MAXPGPATH);
- strncpy(parent, dirname(copy), MAXPGPATH);
+
+ parent = pstrdup(dir);
+ get_parent_directory(parent);
/* Create parent first */
if (access(parent, F_OK) == -1)
@@ -119,6 +120,7 @@ dir_create_dir(const char *dir, mode_t mode)
elog(ERROR, "cannot create directory \"%s\": %s", dir, strerror(errno));
}
+ pfree(parent);
return 0;
}
@@ -153,6 +155,8 @@ pgFileInit(const char *path)
file = (pgFile *) pgut_malloc(sizeof(pgFile));
+ file->name = 0;
+
file->size = 0;
file->mode = 0;
file->read_size = 0;
@@ -232,7 +236,7 @@ pgFileGetCRC(pgFile *file)
int errno_tmp;
/* open file in binary read mode */
- fp = fopen(file->path, "r");
+ fp = fopen(file->path, PG_BINARY_R);
if (fp == NULL)
elog(ERROR, "cannot open file \"%s\": %s",
file->path, strerror(errno));
@@ -350,7 +354,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
char black_item[MAXPGPATH * 2];
black_list = parray_new();
- black_list_file = fopen(path, "r");
+ black_list_file = fopen(path, PG_BINARY_R);
if (black_list_file == NULL)
elog(ERROR, "cannot open black_list: %s", strerror(errno));
@@ -827,7 +831,11 @@ print_file_list(FILE *out, const parray *files, const char *root)
if (file->is_datafile)
fprintf(out, ",\"segno\":\"%d\"", file->segno);
+#ifndef WIN32
if (S_ISLNK(file->mode))
+#else
+ if (pgwin32_is_junction(file->path))
+#endif
fprintf(out, ",\"linked\":\"%s\"", file->linked);
if (file->n_blocks != -1)
diff --git a/src/pg_probackup.c b/src/pg_probackup.c
index efb8e6a3..c66179e1 100644
--- a/src/pg_probackup.c
+++ b/src/pg_probackup.c
@@ -10,6 +10,7 @@
#include "pg_probackup.h"
#include "streamutil.h"
+#include "utils/thread.h"
#include
#include
@@ -207,11 +208,7 @@ main(int argc, char *argv[])
/*
* Save main thread's tid. It is used call exit() in case of errors.
*/
-#ifdef WIN32
- main_tid = GetCurrentThreadId();
-#else
main_tid = pthread_self();
-#endif
/* Parse subcommands and non-subcommand options */
if (argc > 1)
@@ -235,7 +232,7 @@ main(int argc, char *argv[])
else if (strcmp(argv[1], "show") == 0)
backup_subcmd = SHOW;
else if (strcmp(argv[1], "delete") == 0)
- backup_subcmd = DELETE;
+ backup_subcmd = DELETE_SUBCMD;
else if (strcmp(argv[1], "set-config") == 0)
backup_subcmd = SET_CONFIG;
else if (strcmp(argv[1], "show-config") == 0)
@@ -281,7 +278,7 @@ main(int argc, char *argv[])
if (backup_subcmd == BACKUP ||
backup_subcmd == RESTORE ||
backup_subcmd == VALIDATE ||
- backup_subcmd == DELETE)
+ backup_subcmd == DELETE_SUBCMD)
{
int i,
len = 0,
@@ -325,6 +322,7 @@ main(int argc, char *argv[])
if (backup_path == NULL)
elog(ERROR, "required parameter not specified: BACKUP_PATH (-B, --backup-path)");
}
+ canonicalize_path(backup_path);
/* Ensure that backup_path is an absolute path */
if (!is_absolute_path(backup_path))
@@ -402,7 +400,7 @@ main(int argc, char *argv[])
{
if (backup_subcmd != RESTORE
&& backup_subcmd != VALIDATE
- && backup_subcmd != DELETE
+ && backup_subcmd != DELETE_SUBCMD
&& backup_subcmd != SHOW)
elog(ERROR, "Cannot use -i (--backup-id) option together with the '%s' command",
argv[1]);
@@ -464,6 +462,7 @@ main(int argc, char *argv[])
start_time = time(NULL);
backup_mode = deparse_backup_mode(current.backup_mode);
+ current.stream = stream_wal;
elog(INFO, "Backup start, pg_probackup version: %s, backup ID: %s, backup mode: %s, instance: %s, stream: %s, remote: %s",
PROGRAM_VERSION, base36enc(start_time), backup_mode, instance_name,
@@ -484,7 +483,7 @@ main(int argc, char *argv[])
false);
case SHOW:
return do_show(current.backup_id);
- case DELETE:
+ case DELETE_SUBCMD:
if (delete_expired && backup_id_string_param)
elog(ERROR, "You cannot specify --delete-expired and --backup-id options together");
if (!delete_expired && !delete_wal && !backup_id_string_param)
diff --git a/src/pg_probackup.h b/src/pg_probackup.h
index d3ce8241..8face84d 100644
--- a/src/pg_probackup.h
+++ b/src/pg_probackup.h
@@ -15,10 +15,6 @@
#include
#include
-#ifndef WIN32
-#include
-#endif
-
#include "access/timeline.h"
#include "access/xlogdefs.h"
#include "access/xlog_internal.h"
@@ -28,6 +24,13 @@
#include "storage/checksum.h"
#include "utils/pg_crc.h"
#include "common/relpath.h"
+#include "port.h"
+
+#ifdef FRONTEND
+#undef FRONTEND
+ #include "port/atomics.h"
+#define FRONTEND
+#endif
#include "utils/parray.h"
#include "utils/pgut.h"
@@ -102,7 +105,7 @@ typedef struct pgFile
bool is_database;
bool exists_in_prev; /* Mark files, both data and regular, that exists in previous backup */
CompressAlg compress_alg; /* compression algorithm applied to the file */
- volatile uint32 lock; /* lock for synchronization of parallel threads */
+ volatile pg_atomic_flag lock; /* lock for synchronization of parallel threads */
datapagemap_t pagemap; /* bitmap of pages updated since previous backup */
} pgFile;
@@ -144,7 +147,7 @@ typedef enum ProbackupSubcmd
RESTORE,
VALIDATE,
SHOW,
- DELETE,
+ DELETE_SUBCMD,
SET_CONFIG,
SHOW_CONFIG
} ProbackupSubcmd;
@@ -531,4 +534,16 @@ extern void pgBackup_init(pgBackup *backup);
/* in status.c */
extern bool is_pg_running(void);
+#ifdef WIN32
+#ifdef _DEBUG
+#define lseek _lseek
+#define open _open
+#define fstat _fstat
+#define read _read
+#define close _close
+#define write _write
+#define mkdir(dir,mode) _mkdir(dir)
+#endif
+#endif
+
#endif /* PG_PROBACKUP_H */
diff --git a/src/restore.c b/src/restore.c
index 69bac841..0e42c4c4 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -14,14 +14,14 @@
#include
#include
#include
-#include
#include "catalog/pg_control.h"
+#include "utils/thread.h"
typedef struct
{
- parray *files;
- pgBackup *backup;
+ parray *files;
+ pgBackup *backup;
/*
* Return value from the thread.
@@ -65,7 +65,7 @@ static void check_tablespace_mapping(pgBackup *backup);
static void create_recovery_conf(time_t backup_id,
pgRecoveryTarget *rt,
pgBackup *backup);
-static void restore_files(void *arg);
+static void *restore_files(void *arg);
static void remove_deleted_files(pgBackup *backup);
static const char *get_tablespace_mapping(const char *dir);
static void set_tablespace_created(const char *link, const char *dir);
@@ -80,13 +80,11 @@ static TablespaceCreatedList tablespace_created_dirs = {NULL, NULL};
* Entry point of pg_probackup RESTORE and VALIDATE subcommands.
*/
int
-do_restore_or_validate(time_t target_backup_id,
- pgRecoveryTarget *rt,
- bool is_restore)
+do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
+ bool is_restore)
{
int i;
parray *backups;
- parray *timelines;
pgBackup *current_backup = NULL;
pgBackup *dest_backup = NULL;
pgBackup *base_full_backup = NULL;
@@ -169,6 +167,8 @@ do_restore_or_validate(time_t target_backup_id,
if (rt->recovery_target_tli)
{
+ parray *timelines;
+
elog(LOG, "target timeline ID = %u", rt->recovery_target_tli);
/* Read timeline history files from archives */
timelines = readTimeLineHistory_probackup(rt->recovery_target_tli);
@@ -362,8 +362,9 @@ restore_backup(pgBackup *backup)
char list_path[MAXPGPATH];
parray *files;
int i;
- pthread_t restore_threads[num_threads];
- restore_files_args *restore_threads_args[num_threads];
+ /* arrays with meta info for multi threaded backup */
+ pthread_t *restore_threads;
+ restore_files_args *restore_threads_args;
bool restore_isok = true;
if (backup->status != BACKUP_STATUS_OK)
@@ -397,17 +398,21 @@ restore_backup(pgBackup *backup)
pgBackupGetPath(backup, list_path, lengthof(list_path), DATABASE_FILE_LIST);
files = dir_read_file_list(database_path, list_path);
+ restore_threads = (pthread_t *) palloc(sizeof(pthread_t)*num_threads);
+ restore_threads_args = (restore_files_args *) palloc(sizeof(restore_files_args)*num_threads);
+
/* setup threads */
for (i = 0; i < parray_num(files); i++)
{
pgFile *file = (pgFile *) parray_get(files, i);
- __sync_lock_release(&file->lock);
+ pg_atomic_clear_flag(&file->lock);
}
/* Restore files into target directory */
for (i = 0; i < num_threads; i++)
{
- restore_files_args *arg = pg_malloc(sizeof(restore_files_args));
+ restore_files_args *arg = &(restore_threads_args[i]);
+
arg->files = files;
arg->backup = backup;
/* By default there are some error */
@@ -415,23 +420,22 @@ restore_backup(pgBackup *backup)
elog(LOG, "Start thread for num:%li", parray_num(files));
- restore_threads_args[i] = arg;
- pthread_create(&restore_threads[i], NULL,
- (void *(*)(void *)) restore_files, arg);
+ pthread_create(&restore_threads[i], NULL, restore_files, arg);
}
/* Wait theads */
for (i = 0; i < num_threads; i++)
{
pthread_join(restore_threads[i], NULL);
- if (restore_threads_args[i]->ret == 1)
+ if (restore_threads_args[i].ret == 1)
restore_isok = false;
-
- pg_free(restore_threads_args[i]);
}
if (!restore_isok)
elog(ERROR, "Data files restoring failed");
+ pfree(restore_threads);
+ pfree(restore_threads_args);
+
/* cleanup */
parray_walk(files, pgFileFree);
parray_free(files);
@@ -452,7 +456,7 @@ remove_deleted_files(pgBackup *backup)
parray *files;
parray *files_restored;
char filelist_path[MAXPGPATH];
- int i;
+ int i;
pgBackupGetPath(backup, filelist_path, lengthof(filelist_path), DATABASE_FILE_LIST);
/* Read backup's filelist using target database path as base path */
@@ -702,7 +706,7 @@ check_tablespace_mapping(pgBackup *backup)
/*
* Restore files into $PGDATA.
*/
-static void
+static void *
restore_files(void *arg)
{
int i;
@@ -714,7 +718,7 @@ restore_files(void *arg)
char *rel_path;
pgFile *file = (pgFile *) parray_get(arguments->files, i);
- if (__sync_lock_test_and_set(&file->lock, 1) != 0)
+ if (!pg_atomic_test_set_flag(&file->lock))
continue;
pgBackupGetPath(arguments->backup, from_root,
@@ -779,6 +783,8 @@ restore_files(void *arg)
/* Data files restoring is successful */
arguments->ret = 0;
+
+ return NULL;
}
/* Create recovery.conf with given recovery target parameters */
@@ -787,9 +793,9 @@ create_recovery_conf(time_t backup_id,
pgRecoveryTarget *rt,
pgBackup *backup)
{
- char path[MAXPGPATH];
- FILE *fp;
- bool need_restore_conf = false;
+ char path[MAXPGPATH];
+ FILE *fp;
+ bool need_restore_conf = false;
if (!backup->stream
|| (rt->time_specified || rt->xid_specified))
@@ -959,7 +965,8 @@ readTimeLineHistory_probackup(TimeLineID targetTLI)
entry = pgut_new(TimeLineHistoryEntry);
entry->tli = targetTLI;
/* LSN in target timeline is valid */
- entry->end = (uint32) (-1UL << 32) | -1UL;
+ /* TODO ensure that -1UL --> -1L fix is correct */
+ entry->end = (uint32) (-1L << 32) | -1L;
parray_insert(result, 0, entry);
return result;
@@ -980,10 +987,13 @@ satisfy_recovery_target(const pgBackup *backup, const pgRecoveryTarget *rt)
bool
satisfy_timeline(const parray *timelines, const pgBackup *backup)
{
- int i;
+ int i;
+
for (i = 0; i < parray_num(timelines); i++)
{
- TimeLineHistoryEntry *timeline = (TimeLineHistoryEntry *) parray_get(timelines, i);
+ TimeLineHistoryEntry *timeline;
+
+ timeline = (TimeLineHistoryEntry *) parray_get(timelines, i);
if (backup->tli == timeline->tli &&
backup->stop_lsn < timeline->end)
return true;
@@ -1003,14 +1013,14 @@ parseRecoveryTargetOptions(const char *target_time,
const char *target_name,
const char *target_action)
{
- time_t dummy_time;
- TransactionId dummy_xid;
- bool dummy_bool;
+ time_t dummy_time;
+ TransactionId dummy_xid;
+ bool dummy_bool;
/*
* count the number of the mutually exclusive options which may specify
* recovery target. If final value > 1, throw an error.
*/
- int recovery_target_specified = 0;
+ int recovery_target_specified = 0;
pgRecoveryTarget *rt = pgut_new(pgRecoveryTarget);
/* fill all options with default values */
diff --git a/src/status.c b/src/status.c
index 1c7c6038..155a07f4 100644
--- a/src/status.c
+++ b/src/status.c
@@ -38,7 +38,7 @@ get_pgpid(void)
snprintf(pid_file, lengthof(pid_file), "%s/postmaster.pid", pgdata);
- pidf = fopen(pid_file, "r");
+ pidf = fopen(pid_file, PG_BINARY_R);
if (pidf == NULL)
{
/* No pid file, not an error on startup */
diff --git a/src/utils/logger.c b/src/utils/logger.c
index 0a4f835b..8fd78739 100644
--- a/src/utils/logger.c
+++ b/src/utils/logger.c
@@ -8,7 +8,6 @@
*/
#include
-#include
#include
#include
#include
@@ -16,6 +15,7 @@
#include "logger.h"
#include "pgut.h"
+#include "thread.h"
/* Logger parameters */
@@ -69,6 +69,9 @@ static bool exit_hook_registered = false;
static bool loggin_in_progress = false;
static pthread_mutex_t log_file_mutex = PTHREAD_MUTEX_INITIALIZER;
+#ifdef WIN32
+static long mutex_initlock = 0;
+#endif
void
init_logger(const char *root_path)
@@ -138,11 +141,10 @@ exit_if_necessary(int elevel)
}
/* If this is not the main thread then don't call exit() */
+ if (main_tid != pthread_self())
#ifdef WIN32
- if (main_tid != GetCurrentThreadId())
ExitThread(elevel);
#else
- if (!pthread_equal(main_tid, pthread_self()))
pthread_exit(NULL);
#endif
else
@@ -174,6 +176,16 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
/*
* There is no need to lock if this is elog() from upper elog().
*/
+#ifdef WIN32
+ if (log_file_mutex == NULL)
+ {
+ while (InterlockedExchange(&mutex_initlock, 1) == 1)
+ /* loop, another thread own the lock */ ;
+ if (log_file_mutex == NULL)
+ pthread_mutex_init(&log_file_mutex, NULL);
+ InterlockedExchange(&mutex_initlock, 0);
+ }
+#endif
pthread_mutex_lock(&log_file_mutex);
loggin_in_progress = true;
@@ -550,7 +562,7 @@ open_logfile(FILE **file, const char *filename_format)
{
char buf[1024];
- control_file = fopen(control, "r");
+ control_file = fopen(control, PG_BINARY_R);
if (control_file == NULL)
elog_stderr(ERROR, "cannot open rotation file \"%s\": %s",
control, strerror(errno));
@@ -596,7 +608,7 @@ logfile_open:
{
time_t timestamp = time(NULL);
- control_file = fopen(control, "w");
+ control_file = fopen(control, PG_BINARY_W);
if (control_file == NULL)
elog_stderr(ERROR, "cannot open rotation file \"%s\": %s",
control, strerror(errno));
diff --git a/src/utils/pgut.c b/src/utils/pgut.c
index 56263cfa..1a7aae0b 100644
--- a/src/utils/pgut.c
+++ b/src/utils/pgut.c
@@ -42,12 +42,6 @@ static char *password = NULL;
bool prompt_password = true;
bool force_password = false;
-#ifdef WIN32
-DWORD main_tid = 0;
-#else
-pthread_t main_tid = 0;
-#endif
-
/* Database connections */
static PGcancel *volatile cancel_conn = NULL;
@@ -995,7 +989,7 @@ longopts_to_optstring(const struct option opts[], const size_t len)
s = result;
for (i = 0; i < len; i++)
{
- if (!isprint(opts[i].val))
+ if (!isprint(opts[i].val)) //opts[i].val > 128 ||
continue;
*s++ = opts[i].val;
if (opts[i].has_arg != no_argument)
@@ -1052,6 +1046,7 @@ pgut_getopt(int argc, char **argv, pgut_option options[])
struct option *longopts;
size_t len;
+
len = option_length(options);
longopts = pgut_newarray(struct option, len + 1);
option_copy(longopts, options, len);
@@ -1059,6 +1054,7 @@ pgut_getopt(int argc, char **argv, pgut_option options[])
optstring = longopts_to_optstring(longopts, len);
/* Assign named options */
+ optind = 2;
while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1)
{
opt = option_find(c, options);
@@ -1225,7 +1221,7 @@ get_next_token(const char *src, char *dst, const char *line)
}
else
{
- i = j = strcspn(s, "# \n\r\t\v");
+ i = j = strcspn(s, "#\n\r\t\v");//removed space
memcpy(dst, s, j);
}
diff --git a/src/utils/pgut.h b/src/utils/pgut.h
index 803d2c57..a27cea83 100644
--- a/src/utils/pgut.h
+++ b/src/utils/pgut.h
@@ -15,7 +15,6 @@
#include "pqexpbuffer.h"
#include
-#include
#include
#include "logger.h"
@@ -94,13 +93,6 @@ extern const char *PROGRAM_VERSION;
extern const char *PROGRAM_URL;
extern const char *PROGRAM_EMAIL;
-/* ID of the main thread */
-#ifdef WIN32
-extern DWORD main_tid;
-#else
-extern pthread_t main_tid;
-#endif
-
extern void pgut_help(bool details);
/*
diff --git a/src/utils/thread.c b/src/utils/thread.c
new file mode 100644
index 00000000..da3544a1
--- /dev/null
+++ b/src/utils/thread.c
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * thread.c: - multi-platform pthread implementations.
+ *
+ * Copyright (c) 2018, Postgres Professional
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "thread.h"
+
+pthread_t main_tid = 0;
+
+#ifdef WIN32
+
+typedef struct win32_pthread
+{
+ HANDLE handle;
+ void *(*routine) (void *);
+ void *arg;
+ void *result;
+} win32_pthread;
+
+static unsigned __stdcall
+win32_pthread_run(void *arg)
+{
+ win32_pthread *th = (win32_pthread *)arg;
+
+ th->result = th->routine(th->arg);
+
+ return 0;
+}
+
+int
+pthread_create(pthread_t *thread,
+ pthread_attr_t *attr,
+ void *(*start_routine) (void *),
+ void *arg)
+{
+ int save_errno;
+ win32_pthread *th;
+
+ th = (win32_pthread *)pg_malloc(sizeof(win32_pthread));
+ th->routine = start_routine;
+ th->arg = arg;
+ th->result = NULL;
+
+ th->handle = (HANDLE)_beginthreadex(NULL, 0, win32_pthread_run, th, 0, NULL);
+ if (th->handle == NULL)
+ {
+ save_errno = errno;
+ free(th);
+ return save_errno;
+ }
+
+ *thread = th;
+ return 0;
+}
+
+int
+pthread_join(pthread_t th, void **thread_return)
+{
+ if (th == NULL || th->handle == NULL)
+ return errno = EINVAL;
+
+ if (WaitForSingleObject(th->handle, INFINITE) != WAIT_OBJECT_0)
+ {
+ _dosmaperr(GetLastError());
+ return errno;
+ }
+
+ if (thread_return)
+ *thread_return = th->result;
+
+ CloseHandle(th->handle);
+ free(th);
+ return 0;
+}
+
+#endif /* WIN32 */
diff --git a/src/utils/thread.h b/src/utils/thread.h
new file mode 100644
index 00000000..0a113d58
--- /dev/null
+++ b/src/utils/thread.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * thread.h: - multi-platform pthread implementations.
+ *
+ * Copyright (c) 2018, Postgres Professional
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PROBACKUP_THREAD_H
+#define PROBACKUP_THREAD_H
+
+#ifdef WIN32
+#include "port/pthread-win32.h"
+
+/* Use native win32 threads on Windows */
+typedef struct win32_pthread *pthread_t;
+typedef int pthread_attr_t;
+
+#define PTHREAD_MUTEX_INITIALIZER NULL //{ NULL, 0 }
+#define PTHREAD_ONCE_INIT false
+
+extern int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
+extern int pthread_join(pthread_t th, void **thread_return);
+#else
+/* Use platform-dependent pthread capability */
+#include
+#endif
+
+extern pthread_t main_tid;
+
+#endif /* PROBACKUP_THREAD_H */
diff --git a/src/validate.c b/src/validate.c
index afc7f07d..cb693268 100644
--- a/src/validate.c
+++ b/src/validate.c
@@ -11,10 +11,11 @@
#include "pg_probackup.h"
#include
-#include
#include
-static void pgBackupValidateFiles(void *arg);
+#include "utils/thread.h"
+
+static void *pgBackupValidateFiles(void *arg);
static void do_validate_instance(void);
static bool corrupted_backup_found = false;
@@ -42,8 +43,9 @@ pgBackupValidate(pgBackup *backup)
parray *files;
bool corrupted = false;
bool validation_isok = true;
- pthread_t validate_threads[num_threads];
- validate_files_args *validate_threads_args[num_threads];
+ /* arrays with meta info for multi threaded validate */
+ pthread_t *validate_threads;
+ validate_files_args *validate_threads_args;
int i;
/* Revalidation is attempted for DONE, ORPHAN and CORRUPT backups */
@@ -77,36 +79,44 @@ pgBackupValidate(pgBackup *backup)
for (i = 0; i < parray_num(files); i++)
{
pgFile *file = (pgFile *) parray_get(files, i);
- __sync_lock_release(&file->lock);
+ pg_atomic_clear_flag(&file->lock);
}
+ /* init thread args with own file lists */
+ validate_threads = (pthread_t *) palloc(sizeof(pthread_t) * num_threads);
+ validate_threads_args = (validate_files_args *)
+ palloc(sizeof(validate_files_args) * num_threads);
+
/* Validate files */
for (i = 0; i < num_threads; i++)
{
- validate_files_args *arg = pg_malloc(sizeof(validate_files_args));
+ validate_files_args *arg = &(validate_threads_args[i]);
+
arg->files = files;
arg->corrupted = false;
/* By default there are some error */
arg->ret = 1;
- validate_threads_args[i] = arg;
- pthread_create(&validate_threads[i], NULL,
- (void *(*)(void *)) pgBackupValidateFiles, arg);
+ pthread_create(&validate_threads[i], NULL, pgBackupValidateFiles, arg);
}
/* Wait theads */
for (i = 0; i < num_threads; i++)
{
+ validate_files_args *arg = &(validate_threads_args[i]);
+
pthread_join(validate_threads[i], NULL);
- if (validate_threads_args[i]->corrupted)
+ if (arg->corrupted)
corrupted = true;
- if (validate_threads_args[i]->ret == 1)
+ if (arg->ret == 1)
validation_isok = false;
- pg_free(validate_threads_args[i]);
}
if (!validation_isok)
elog(ERROR, "Data files validation failed");
+ pfree(validate_threads);
+ pfree(validate_threads_args);
+
/* cleanup */
parray_walk(files, pgFileFree);
parray_free(files);
@@ -127,10 +137,10 @@ pgBackupValidate(pgBackup *backup)
* rather throw a WARNING and set arguments->corrupted = true.
* This is necessary to update backup status.
*/
-static void
+static void *
pgBackupValidateFiles(void *arg)
{
- int i;
+ int i;
validate_files_args *arguments = (validate_files_args *)arg;
pg_crc32 crc;
@@ -139,7 +149,7 @@ pgBackupValidateFiles(void *arg)
struct stat st;
pgFile *file = (pgFile *) parray_get(arguments->files, i);
- if (__sync_lock_test_and_set(&file->lock, 1) != 0)
+ if (!pg_atomic_test_set_flag(&file->lock))
continue;
if (interrupted)
@@ -198,6 +208,8 @@ pgBackupValidateFiles(void *arg)
/* Data files validation is successful */
arguments->ret = 0;
+
+ return NULL;
}
/*
@@ -267,7 +279,7 @@ do_validate_all(void)
static void
do_validate_instance(void)
{
- char *current_backup_id;
+ char *current_backup_id;
int i;
parray *backups;
pgBackup *current_backup = NULL;
diff --git a/win32build.pl b/win32build.pl
new file mode 100644
index 00000000..14864181
--- /dev/null
+++ b/win32build.pl
@@ -0,0 +1,240 @@
+#!/usr/bin/perl
+use JSON;
+our $repack_version;
+our $pgdir;
+our $pgsrc;
+if (@ARGV!=2) {
+ print STDERR "Usage $0 postgress-instalation-root pg-source-dir \n";
+ exit 1;
+}
+
+
+our $liblist="";
+
+
+$pgdir = shift @ARGV;
+$pgsrc = shift @ARGV if @ARGV;
+
+
+our $arch = $ENV{'ARCH'} || "x64";
+$arch='Win32' if ($arch eq 'x86' || $arch eq 'X86');
+$arch='x64' if $arch eq 'X64';
+
+$conffile = $pgsrc."/tools/msvc/config.pl";
+
+
+die 'Could not find config.pl'
+ unless (-f $conffile);
+
+our $config;
+do $conffile;
+
+
+if (! -d "$pgdir/bin" || !-d "$pgdir/include" || !-d "$pgdir/lib") {
+ print STDERR "Directory $pgdir doesn't look like root of postgresql installation\n";
+ exit 1;
+}
+our $includepath="";
+our $libpath="";
+our $libpath32="";
+AddProject();
+
+print "\n\n";
+print $libpath."\n";
+print $includepath."\n";
+
+# open F,"<","META.json" or die "Cannot open META.json: $!\n";
+# {
+# local $/ = undef;
+# $decoded = decode_json();
+# $repack_version= $decoded->{'version'};
+# }
+
+# substitute new path in the project files
+
+
+
+preprocess_project("./msvs/template.pg_probackup.vcxproj","./msvs/pg_probackup.vcxproj");
+
+exit 0;
+
+
+sub preprocess_project {
+ my $in = shift;
+ my $out = shift;
+ our $pgdir;
+ our $adddir;
+ my $libs;
+ if (defined $adddir) {
+ $libs ="$adddir;";
+ } else{
+ $libs ="";
+ }
+ open IN,"<",$in or die "Cannot open $in: $!\n";
+ open OUT,">",$out or die "Cannot open $out: $!\n";
+
+# $includepath .= ";";
+# $libpath .= ";";
+
+ while () {
+ s/\@PGROOT\@/$pgdir/g;
+ s/\@ADDLIBS\@/$libpath/g;
+ s/\@ADDLIBS32\@/$libpath32/g;
+ s/\@PGSRC\@/$pgsrc/g;
+ s/\@ADDINCLUDE\@/$includepath/g;
+
+
+ print OUT $_;
+ }
+ close IN;
+ close OUT;
+
+}
+
+
+
+# my sub
+sub AddLibrary
+{
+ $inc = shift;
+ if ($libpath ne '')
+ {
+ $libpath .= ';';
+ }
+ $libpath .= $inc;
+ if ($libpath32 ne '')
+ {
+ $libpath32 .= ';';
+ }
+ $libpath32 .= $inc;
+
+}
+sub AddLibrary32
+{
+ $inc = shift;
+ if ($libpath32 ne '')
+ {
+ $libpath32 .= ';';
+ }
+ $libpath32 .= $inc;
+
+}
+sub AddLibrary64
+{
+ $inc = shift;
+ if ($libpath ne '')
+ {
+ $libpath .= ';';
+ }
+ $libpath .= $inc;
+
+}
+
+sub AddIncludeDir
+{
+ # my ($self, $inc) = @_;
+ $inc = shift;
+ if ($includepath ne '')
+ {
+ $includepath .= ';';
+ }
+ $includepath .= $inc;
+
+}
+
+sub AddProject
+{
+ # my ($self, $name, $type, $folder, $initialdir) = @_;
+
+ if ($config->{zlib})
+ {
+ AddIncludeDir($config->{zlib} . '\include');
+ AddLibrary($config->{zlib} . '\lib\zdll.lib');
+ }
+ if ($config->{openssl})
+ {
+ AddIncludeDir($config->{openssl} . '\include');
+ if (-e "$config->{openssl}/lib/VC/ssleay32MD.lib")
+ {
+ AddLibrary(
+ $config->{openssl} . '\lib\VC\ssleay32.lib', 1);
+ AddLibrary(
+ $config->{openssl} . '\lib\VC\libeay32.lib', 1);
+ }
+ else
+ {
+ # We don't expect the config-specific library to be here,
+ # so don't ask for it in last parameter
+ AddLibrary(
+ $config->{openssl} . '\lib\ssleay32.lib', 0);
+ AddLibrary(
+ $config->{openssl} . '\lib\libeay32.lib', 0);
+ }
+ }
+ if ($config->{nls})
+ {
+ AddIncludeDir($config->{nls} . '\include');
+ AddLibrary($config->{nls} . '\lib\libintl.lib');
+ }
+ if ($config->{gss})
+ {
+ AddIncludeDir($config->{gss} . '\inc\krb5');
+ AddLibrary($config->{gss} . '\lib\i386\krb5_32.lib');
+ AddLibrary($config->{gss} . '\lib\i386\comerr32.lib');
+ AddLibrary($config->{gss} . '\lib\i386\gssapi32.lib');
+ }
+ if ($config->{iconv})
+ {
+ AddIncludeDir($config->{iconv} . '\include');
+ AddLibrary($config->{iconv} . '\lib\iconv.lib');
+ }
+ if ($config->{icu})
+ {
+ AddIncludeDir($config->{icu} . '\include');
+ AddLibrary32($config->{icu} . '\lib\icuin.lib');
+ AddLibrary32($config->{icu} . '\lib\icuuc.lib');
+ AddLibrary32($config->{icu} . '\lib\icudt.lib');
+ AddLibrary64($config->{icu} . '\lib64\icuin.lib');
+ AddLibrary64($config->{icu} . '\lib64\icuuc.lib');
+ AddLibrary64($config->{icu} . '\lib64\icudt.lib');
+ }
+ if ($config->{xml})
+ {
+ AddIncludeDir($config->{xml} . '\include');
+ AddIncludeDir($config->{xml} . '\include\libxml2');
+ AddLibrary($config->{xml} . '\lib\libxml2.lib');
+ }
+ if ($config->{xslt})
+ {
+ AddIncludeDir($config->{xslt} . '\include');
+ AddLibrary($config->{xslt} . '\lib\libxslt.lib');
+ }
+ if ($config->{libedit})
+ {
+ AddIncludeDir($config->{libedit} . '\include');
+ # AddLibrary($config->{libedit} . "\\" .
+ # ($arch eq 'x64'? 'lib64': 'lib32').'\edit.lib');
+ AddLibrary32($config->{libedit} . '\\lib32\edit.lib');
+ AddLibrary64($config->{libedit} . '\\lib64\edit.lib');
+
+
+ }
+ if ($config->{uuid})
+ {
+ AddIncludeDir($config->{uuid} . '\include');
+ AddLibrary($config->{uuid} . '\lib\uuid.lib');
+ }
+
+ if ($config->{zstd})
+ {
+ AddIncludeDir($config->{zstd});
+ # AddLibrary($config->{zstd}. "\\".($arch eq 'x64'? "zstdlib_x64.lib" : "zstdlib_x86.lib"));
+ AddLibrary32($config->{zstd}. "\\zstdlib_x86.lib");
+ AddLibrary64($config->{zstd}. "\\zstdlib_x64.lib") ;
+ }
+ # return $proj;
+}
+
+
+
+
diff --git a/win32build96.pl b/win32build96.pl
new file mode 100644
index 00000000..c869e485
--- /dev/null
+++ b/win32build96.pl
@@ -0,0 +1,240 @@
+#!/usr/bin/perl
+use JSON;
+our $repack_version;
+our $pgdir;
+our $pgsrc;
+if (@ARGV!=2) {
+ print STDERR "Usage $0 postgress-instalation-root pg-source-dir \n";
+ exit 1;
+}
+
+
+our $liblist="";
+
+
+$pgdir = shift @ARGV;
+$pgsrc = shift @ARGV if @ARGV;
+
+
+our $arch = $ENV{'ARCH'} || "x64";
+$arch='Win32' if ($arch eq 'x86' || $arch eq 'X86');
+$arch='x64' if $arch eq 'X64';
+
+$conffile = $pgsrc."/tools/msvc/config.pl";
+
+
+die 'Could not find config.pl'
+ unless (-f $conffile);
+
+our $config;
+do $conffile;
+
+
+if (! -d "$pgdir/bin" || !-d "$pgdir/include" || !-d "$pgdir/lib") {
+ print STDERR "Directory $pgdir doesn't look like root of postgresql installation\n";
+ exit 1;
+}
+our $includepath="";
+our $libpath="";
+our $libpath32="";
+AddProject();
+
+print "\n\n";
+print $libpath."\n";
+print $includepath."\n";
+
+# open F,"<","META.json" or die "Cannot open META.json: $!\n";
+# {
+# local $/ = undef;
+# $decoded = decode_json();
+# $repack_version= $decoded->{'version'};
+# }
+
+# substitute new path in the project files
+
+
+
+preprocess_project("./msvs/template.pg_probackup96.vcxproj","./msvs/pg_probackup.vcxproj");
+
+exit 0;
+
+
+sub preprocess_project {
+ my $in = shift;
+ my $out = shift;
+ our $pgdir;
+ our $adddir;
+ my $libs;
+ if (defined $adddir) {
+ $libs ="$adddir;";
+ } else{
+ $libs ="";
+ }
+ open IN,"<",$in or die "Cannot open $in: $!\n";
+ open OUT,">",$out or die "Cannot open $out: $!\n";
+
+# $includepath .= ";";
+# $libpath .= ";";
+
+ while () {
+ s/\@PGROOT\@/$pgdir/g;
+ s/\@ADDLIBS\@/$libpath/g;
+ s/\@ADDLIBS32\@/$libpath32/g;
+ s/\@PGSRC\@/$pgsrc/g;
+ s/\@ADDINCLUDE\@/$includepath/g;
+
+
+ print OUT $_;
+ }
+ close IN;
+ close OUT;
+
+}
+
+
+
+# my sub
+sub AddLibrary
+{
+ $inc = shift;
+ if ($libpath ne '')
+ {
+ $libpath .= ';';
+ }
+ $libpath .= $inc;
+ if ($libpath32 ne '')
+ {
+ $libpath32 .= ';';
+ }
+ $libpath32 .= $inc;
+
+}
+sub AddLibrary32
+{
+ $inc = shift;
+ if ($libpath32 ne '')
+ {
+ $libpath32 .= ';';
+ }
+ $libpath32 .= $inc;
+
+}
+sub AddLibrary64
+{
+ $inc = shift;
+ if ($libpath ne '')
+ {
+ $libpath .= ';';
+ }
+ $libpath .= $inc;
+
+}
+
+sub AddIncludeDir
+{
+ # my ($self, $inc) = @_;
+ $inc = shift;
+ if ($includepath ne '')
+ {
+ $includepath .= ';';
+ }
+ $includepath .= $inc;
+
+}
+
+sub AddProject
+{
+ # my ($self, $name, $type, $folder, $initialdir) = @_;
+
+ if ($config->{zlib})
+ {
+ AddIncludeDir($config->{zlib} . '\include');
+ AddLibrary($config->{zlib} . '\lib\zdll.lib');
+ }
+ if ($config->{openssl})
+ {
+ AddIncludeDir($config->{openssl} . '\include');
+ if (-e "$config->{openssl}/lib/VC/ssleay32MD.lib")
+ {
+ AddLibrary(
+ $config->{openssl} . '\lib\VC\ssleay32.lib', 1);
+ AddLibrary(
+ $config->{openssl} . '\lib\VC\libeay32.lib', 1);
+ }
+ else
+ {
+ # We don't expect the config-specific library to be here,
+ # so don't ask for it in last parameter
+ AddLibrary(
+ $config->{openssl} . '\lib\ssleay32.lib', 0);
+ AddLibrary(
+ $config->{openssl} . '\lib\libeay32.lib', 0);
+ }
+ }
+ if ($config->{nls})
+ {
+ AddIncludeDir($config->{nls} . '\include');
+ AddLibrary($config->{nls} . '\lib\libintl.lib');
+ }
+ if ($config->{gss})
+ {
+ AddIncludeDir($config->{gss} . '\inc\krb5');
+ AddLibrary($config->{gss} . '\lib\i386\krb5_32.lib');
+ AddLibrary($config->{gss} . '\lib\i386\comerr32.lib');
+ AddLibrary($config->{gss} . '\lib\i386\gssapi32.lib');
+ }
+ if ($config->{iconv})
+ {
+ AddIncludeDir($config->{iconv} . '\include');
+ AddLibrary($config->{iconv} . '\lib\iconv.lib');
+ }
+ if ($config->{icu})
+ {
+ AddIncludeDir($config->{icu} . '\include');
+ AddLibrary32($config->{icu} . '\lib\icuin.lib');
+ AddLibrary32($config->{icu} . '\lib\icuuc.lib');
+ AddLibrary32($config->{icu} . '\lib\icudt.lib');
+ AddLibrary64($config->{icu} . '\lib64\icuin.lib');
+ AddLibrary64($config->{icu} . '\lib64\icuuc.lib');
+ AddLibrary64($config->{icu} . '\lib64\icudt.lib');
+ }
+ if ($config->{xml})
+ {
+ AddIncludeDir($config->{xml} . '\include');
+ AddIncludeDir($config->{xml} . '\include\libxml2');
+ AddLibrary($config->{xml} . '\lib\libxml2.lib');
+ }
+ if ($config->{xslt})
+ {
+ AddIncludeDir($config->{xslt} . '\include');
+ AddLibrary($config->{xslt} . '\lib\libxslt.lib');
+ }
+ if ($config->{libedit})
+ {
+ AddIncludeDir($config->{libedit} . '\include');
+ # AddLibrary($config->{libedit} . "\\" .
+ # ($arch eq 'x64'? 'lib64': 'lib32').'\edit.lib');
+ AddLibrary32($config->{libedit} . '\\lib32\edit.lib');
+ AddLibrary64($config->{libedit} . '\\lib64\edit.lib');
+
+
+ }
+ if ($config->{uuid})
+ {
+ AddIncludeDir($config->{uuid} . '\include');
+ AddLibrary($config->{uuid} . '\lib\uuid.lib');
+ }
+
+ if ($config->{zstd})
+ {
+ AddIncludeDir($config->{zstd});
+ # AddLibrary($config->{zstd}. "\\".($arch eq 'x64'? "zstdlib_x64.lib" : "zstdlib_x86.lib"));
+ AddLibrary32($config->{zstd}. "\\zstdlib_x86.lib");
+ AddLibrary64($config->{zstd}. "\\zstdlib_x64.lib") ;
+ }
+ # return $proj;
+}
+
+
+
+
diff --git a/win32build_2.pl b/win32build_2.pl
new file mode 100644
index 00000000..a4f75553
--- /dev/null
+++ b/win32build_2.pl
@@ -0,0 +1,219 @@
+#!/usr/bin/perl
+use JSON;
+our $repack_version;
+our $pgdir;
+our $pgsrc;
+if (@ARGV!=2) {
+ print STDERR "Usage $0 postgress-instalation-root pg-source-dir \n";
+ exit 1;
+}
+
+
+our $liblist="";
+
+
+$pgdir = shift @ARGV;
+$pgsrc = shift @ARGV if @ARGV;
+
+
+our $arch = $ENV{'ARCH'} || "x64";
+$arch='Win32' if ($arch eq 'x86' || $arch eq 'X86');
+$arch='x64' if $arch eq 'X64';
+
+$conffile = $pgsrc."/tools/msvc/config.pl";
+
+
+die 'Could not find config.pl'
+ unless (-f $conffile);
+
+our $config;
+do $conffile;
+
+
+if (! -d "$pgdir/bin" || !-d "$pgdir/include" || !-d "$pgdir/lib") {
+ print STDERR "Directory $pgdir doesn't look like root of postgresql installation\n";
+ exit 1;
+}
+our $includepath="";
+our $libpath="";
+AddProject();
+
+print "\n\n";
+print $libpath."\n";
+print $includepath."\n";
+
+# open F,"<","META.json" or die "Cannot open META.json: $!\n";
+# {
+# local $/ = undef;
+# $decoded = decode_json();
+# $repack_version= $decoded->{'version'};
+# }
+
+# substitute new path in the project files
+
+
+
+preprocess_project("./msvs/template.pg_probackup_2.vcxproj","./msvs/pg_probackup.vcxproj");
+
+exit 0;
+
+
+sub preprocess_project {
+ my $in = shift;
+ my $out = shift;
+ our $pgdir;
+ our $adddir;
+ my $libs;
+ if (defined $adddir) {
+ $libs ="$adddir;";
+ } else{
+ $libs ="";
+ }
+ open IN,"<",$in or die "Cannot open $in: $!\n";
+ open OUT,">",$out or die "Cannot open $out: $!\n";
+
+# $includepath .= ";";
+# $libpath .= ";";
+
+ while () {
+ s/\@PGROOT\@/$pgdir/g;
+ s/\@ADDLIBS\@/$libpath/g;
+ s/\@PGSRC\@/$pgsrc/g;
+ s/\@ADDINCLUDE\@/$includepath/g;
+
+
+ print OUT $_;
+ }
+ close IN;
+ close OUT;
+
+}
+
+
+
+# my sub
+sub AddLibrary
+{
+ $inc = shift;
+ if ($libpath ne '')
+ {
+ $libpath .= ';';
+ }
+ $libpath .= $inc;
+
+}
+sub AddIncludeDir
+{
+ # my ($self, $inc) = @_;
+ $inc = shift;
+ if ($includepath ne '')
+ {
+ $includepath .= ';';
+ }
+ $includepath .= $inc;
+
+}
+
+sub AddProject
+{
+ # my ($self, $name, $type, $folder, $initialdir) = @_;
+
+ if ($config->{zlib})
+ {
+ AddIncludeDir($config->{zlib} . '\include');
+ AddLibrary($config->{zlib} . '\lib\zdll.lib');
+ }
+ if ($config->{openssl})
+ {
+ AddIncludeDir($config->{openssl} . '\include');
+ if (-e "$config->{openssl}/lib/VC/ssleay32MD.lib")
+ {
+ AddLibrary(
+ $config->{openssl} . '\lib\VC\ssleay32.lib', 1);
+ AddLibrary(
+ $config->{openssl} . '\lib\VC\libeay32.lib', 1);
+ }
+ else
+ {
+ # We don't expect the config-specific library to be here,
+ # so don't ask for it in last parameter
+ AddLibrary(
+ $config->{openssl} . '\lib\ssleay32.lib', 0);
+ AddLibrary(
+ $config->{openssl} . '\lib\libeay32.lib', 0);
+ }
+ }
+ if ($config->{nls})
+ {
+ AddIncludeDir($config->{nls} . '\include');
+ AddLibrary($config->{nls} . '\lib\libintl.lib');
+ }
+ if ($config->{gss})
+ {
+ AddIncludeDir($config->{gss} . '\inc\krb5');
+ AddLibrary($config->{gss} . '\lib\i386\krb5_32.lib');
+ AddLibrary($config->{gss} . '\lib\i386\comerr32.lib');
+ AddLibrary($config->{gss} . '\lib\i386\gssapi32.lib');
+ }
+ if ($config->{iconv})
+ {
+ AddIncludeDir($config->{iconv} . '\include');
+ AddLibrary($config->{iconv} . '\lib\iconv.lib');
+ }
+ if ($config->{icu})
+ {
+ AddIncludeDir($config->{icu} . '\include');
+ if ($arch eq 'Win32')
+ {
+ AddLibrary($config->{icu} . '\lib\icuin.lib');
+ AddLibrary($config->{icu} . '\lib\icuuc.lib');
+ AddLibrary($config->{icu} . '\lib\icudt.lib');
+ }
+ else
+ {
+ AddLibrary($config->{icu} . '\lib64\icuin.lib');
+ AddLibrary($config->{icu} . '\lib64\icuuc.lib');
+ AddLibrary($config->{icu} . '\lib64\icudt.lib');
+ }
+ }
+ if ($config->{xml})
+ {
+ AddIncludeDir($config->{xml} . '\include');
+ AddIncludeDir($config->{xml} . '\include\libxml2');
+ AddLibrary($config->{xml} . '\lib\libxml2.lib');
+ }
+ if ($config->{xslt})
+ {
+ AddIncludeDir($config->{xslt} . '\include');
+ AddLibrary($config->{xslt} . '\lib\libxslt.lib');
+ }
+ if ($config->{libedit})
+ {
+ AddIncludeDir($config->{libedit} . '\include');
+ AddLibrary($config->{libedit} . "\\" .
+ ($arch eq 'x64'? 'lib64': 'lib32').'\edit.lib');
+ }
+ if ($config->{uuid})
+ {
+ AddIncludeDir($config->{uuid} . '\include');
+ AddLibrary($config->{uuid} . '\lib\uuid.lib');
+ }
+ if ($config->{libedit})
+ {
+ AddIncludeDir($config->{libedit} . '\include');
+ AddLibrary($config->{libedit} . "\\" .
+ ($arch eq 'x64'? 'lib64': 'lib32').'\edit.lib');
+ }
+ if ($config->{zstd})
+ {
+ AddIncludeDir($config->{zstd});
+ AddLibrary($config->{zstd}. "\\".
+ ($arch eq 'x64'? "zstdlib_x64.lib" : "zstdlib_x86.lib")
+ );
+ }
+ # return $proj;
+}
+
+
+
+