|
From: <ale...@us...> - 2012-06-20 11:56:44
|
Revision: 54644
http://firebird.svn.sourceforge.net/firebird/?rev=54644&view=rev
Author: alexpeshkoff
Date: 2012-06-20 11:56:36 +0000 (Wed, 20 Jun 2012)
Log Message:
-----------
Backported implementation of CORE-2666: Make it possible to use API to do remote backups/restores
Modified Paths:
--------------
firebird/branches/B2_5_Release/doc/README.services_extension
firebird/branches/B2_5_Release/src/burp/burp.cpp
firebird/branches/B2_5_Release/src/burp/burp.h
firebird/branches/B2_5_Release/src/burp/mvol.cpp
firebird/branches/B2_5_Release/src/burp/spit.cpp
firebird/branches/B2_5_Release/src/burp/spit.h
firebird/branches/B2_5_Release/src/burp/std_desc.h
firebird/branches/B2_5_Release/src/common/UtilSvc.cpp
firebird/branches/B2_5_Release/src/common/UtilSvc.h
firebird/branches/B2_5_Release/src/include/consts_pub.h
firebird/branches/B2_5_Release/src/include/gen/msgs.h
firebird/branches/B2_5_Release/src/jrd/svc.cpp
firebird/branches/B2_5_Release/src/jrd/svc.h
firebird/branches/B2_5_Release/src/lock/lock.cpp
firebird/branches/B2_5_Release/src/msgs/messages2.sql
firebird/branches/B2_5_Release/src/utilities/fbsvcmgr.cpp
Modified: firebird/branches/B2_5_Release/doc/README.services_extension
===================================================================
--- firebird/branches/B2_5_Release/doc/README.services_extension 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/doc/README.services_extension 2012-06-20 11:56:36 UTC (rev 54644)
@@ -31,6 +31,7 @@
Return to normal state:
fbsvcmgr service_mgr action_properties dbname employee prp_online_mode prp_sm_normal
+
2) Services API extension - nbackup support.
(Alex Peshkov, pes...@ma..., 2008)
@@ -82,7 +83,7 @@
Stop trace session
action
- isc_action_svc_trace_stop
+ isc_action_svc_trace_stop
parameter(s)
isc_spb_trc_id : trace session ID, integer, mandatory
@@ -96,7 +97,7 @@
Suspend trace session
action
- isc_action_svc_trace_suspend
+ isc_action_svc_trace_suspend
parameter(s)
isc_spb_trc_id : trace session ID, integer, mandatory
@@ -109,7 +110,7 @@
Resume trace session
action
- isc_action_svc_trace_resume
+ isc_action_svc_trace_resume
parameter(s)
isc_spb_trc_id : trace session ID, integer, mandatory
@@ -122,7 +123,7 @@
List of existing trace sessions
action
- isc_action_svc_trace_list
+ isc_action_svc_trace_list
parameter(s)
none
@@ -134,7 +135,7 @@
- user: <string>
- date: YYYY-MM-DD HH:NN:SS
- flags: <string>
-
+
"name" is trace session name and not printed if empty.
"user" is creator user name
"date" is session start date and time
@@ -149,4 +150,45 @@
Output of every service is obtained as usually using isc_service_query call
with isc_info_svc_line or isc_info_svc_to_eof information items.
-See also README.trace_services
\ No newline at end of file
+See also README.trace_services
+
+
+4) Services API extension - running gbak at server side with .fbk at the client.
+(Alex Peshkov, pes...@ma..., 2011-2012)
+
+This way of doing backups is specially efficient when one needs to perform
+backup/restore operation for database, located on ther server accessed using
+internet, due to serious performance instrease.
+
+The simplest way to use this feature is fbsvcmgr. To backup database run
+approximately the following:
+fbsvcmgr remotehost:service_mgr -user sysdba -password XXX \
+ action_backup -dbname some.fdb -bkp_file stdout >some.fbk
+
+and to restore it:
+fbsvcmgr remotehost:service_mgr -user sysdba -password XXX \
+ action_restore -dbname some.fdb -bkp_file stdin <some.fbk
+
+Please notice - you can't use "verbose" switch when performing backup because
+data channel from server to client is used to deliver blocks of fbk files. You
+will get appropriate error message if you try to do it. When restoring database
+verbose mode may be used without limitations.
+
+If you want to perform backup/restore from your own program, you should use
+services API for it. Backup is very simple - just pass "stdout" as backup file
+name to server and use isc_info_svc_to_eof in isc_service_query() call. Data,
+returned by repeating calls to isc_service_query() (certainly with
+isc_info_svc_to_eof tag) is a stream, representing image of backup file. Restore
+is a bit more tricky. Client sends new spb parameter isc_info_svc_stdin to server
+in isc_service_query(). If service needs some data in stdin, it returns
+isc_info_svc_stdin in query results, followed by 4-bytes value - number of bytes
+server is ready to accept from client. (0 value means no more data is needed right
+now.) The main trick is that client should NOT send more data than requested by
+server - this causes an error "Size of data is more than requested". The data is
+sent in next isc_service_query() call in the send_items block, using
+isc_info_svc_line tag in tradition form: isc_info_svc_line, 2 bytes length, data.
+When server needs next portion, it once more returns non-zero isc_info_svc_stdin
+value from isc_service_query().
+
+A sample of how services API should be used for remote backup and restore can be
+found in source code of fbsvcmgr.
Modified: firebird/branches/B2_5_Release/src/burp/burp.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/burp/burp.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/burp/burp.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -1127,12 +1127,17 @@
// Close the gbak file handles if they still open
for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
{
- if (file->fil_fd != INVALID_HANDLE_VALUE)
- close_platf(file->fil_fd);
- if (exit_code != FINI_OK &&
- (tdgbl->action->act_action == ACT_backup_split || tdgbl->action->act_action == ACT_backup))
+ if (file->fil_fd != GBAK_STDIN_DESC() && file->fil_fd != GBAK_STDOUT_DESC())
{
- unlink_platf(file->fil_name.c_str());
+ if (file->fil_fd != INVALID_HANDLE_VALUE)
+ {
+ close_platf(file->fil_fd);
+ }
+ if (exit_code != FINI_OK &&
+ (tdgbl->action->act_action == ACT_backup_split || tdgbl->action->act_action == ACT_backup))
+ {
+ unlink_platf(file->fil_name.c_str());
+ }
}
}
@@ -1682,10 +1687,10 @@
}
if (fil->fil_name == "stdout")
{
- if (tdgbl->action->act_total >= 2 || fil->fil_next)
+ if (tdgbl->action->act_total >= 2 || fil->fil_next || sw_verbose)
{
BURP_error(266, true);
- // msg 266 standard output is not supported when using split operation
+ // msg 266 standard output is not supported when using split operation or in verbose mode
flag = QUIT;
break;
}
@@ -1697,6 +1702,7 @@
#endif
tdgbl->uSvc->setDataMode(true);
fil->fil_fd = GBAK_STDOUT_DESC();
+ tdgbl->stdIoMode = true;
break;
}
else
@@ -1801,10 +1807,13 @@
{
fil->fil_fd = GBAK_STDIN_DESC();
tdgbl->file_desc = fil->fil_fd;
+ tdgbl->stdIoMode = true;
tdgbl->gbl_sw_files = fil->fil_next;
}
else
{
+ tdgbl->stdIoMode = false;
+
// open first file
#ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_READ, OPEN_EXISTING)) ==
Modified: firebird/branches/B2_5_Release/src/burp/burp.h
===================================================================
--- firebird/branches/B2_5_Release/src/burp/burp.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/burp/burp.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -815,7 +815,8 @@
defaultCollations(*getDefaultMemoryPool()),
flag_on_line(true),
uSvc(us),
- firstMap(true)
+ firstMap(true),
+ stdIoMode(false)
{
// this is VERY dirty hack to keep current behaviour
memset (&gbl_database_file_name, 0,
@@ -977,6 +978,7 @@
bool flag_on_line; // indicates whether we will bring the database on-line
Firebird::UtilSvc* uSvc;
bool firstMap; // this is the first time we entered get_mapping()
+ bool stdIoMode; // stdin or stdout is used as backup file
};
// CVC: This aux routine declared here to not force inclusion of burp.h with burp_proto.h
@@ -988,17 +990,8 @@
indices */
// I/O definitions
+const int GBAK_IO_BUFFER_SIZE = SVC_IO_BUFFER_SIZE;
-#ifndef IO_BUFFER_SIZE
-#ifdef BUFSIZ
-const int GBAK_IO_BUFFER_SIZE = (16 * (BUFSIZ));
-#else
-const int GBAK_IO_BUFFER_SIZE = (16 * (1024));
-#endif
-#else
-const int GBAK_IO_BUFFER_SIZE = (16 * (IO_BUFFER_SIZE));
-#endif
-
/* Burp will always write a backup in multiples of the following number
* of bytes. The initial value is the smallest which ensures that writes
* to fixed-block SCSI tapes such as QIC-150 will work. The value should
Modified: firebird/branches/B2_5_Release/src/burp/mvol.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/burp/mvol.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/burp/mvol.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -100,6 +100,7 @@
static bool read_header(DESC, ULONG*, USHORT*, bool);
static bool write_header(DESC, ULONG, bool);
static DESC next_volume(DESC, ULONG, bool);
+static void mvol_read(int*, UCHAR**);
//____________________________________________________________
@@ -109,15 +110,16 @@
{
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
- if (strcmp(tdgbl->mvol_old_file, "stdin") != 0)
+ if (!tdgbl->stdIoMode)
{
close_platf(tdgbl->file_desc);
+ }
- for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ {
+ if (file->fil_fd == tdgbl->file_desc)
{
- if (file->fil_fd == tdgbl->file_desc) {
- file->fil_fd = INVALID_HANDLE_VALUE;
- }
+ file->fil_fd = INVALID_HANDLE_VALUE;
}
}
@@ -139,15 +141,19 @@
MVOL_write(rec_end, io_cnt, io_ptr);
flush_platf(tdgbl->file_desc);
- if (strcmp(tdgbl->mvol_old_file, "stdout") != 0)
+
+ if (!tdgbl->stdIoMode)
{
close_platf(tdgbl->file_desc);
- for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ }
+ for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ {
+ if (file->fil_fd == tdgbl->file_desc)
{
- if (file->fil_fd == tdgbl->file_desc)
- file->fil_fd = INVALID_HANDLE_VALUE;
+ file->fil_fd = INVALID_HANDLE_VALUE;
}
}
+
tdgbl->file_desc = INVALID_HANDLE_VALUE;
BURP_free(tdgbl->mvol_io_header);
tdgbl->mvol_io_header = NULL;
@@ -260,12 +266,48 @@
}
+//____________________________________________________________
+//
+// Read a buffer's worth of data. (common)
+//
+int MVOL_read(int* cnt, UCHAR** ptr)
+{
+ BurpGlobals* tdgbl = BurpGlobals::getSpecific();
+
+ if (tdgbl->stdIoMode && tdgbl->uSvc->isService())
+ {
+ tdgbl->uSvc->started();
+ tdgbl->mvol_io_cnt = tdgbl->uSvc->getBytes(tdgbl->mvol_io_buffer, tdgbl->mvol_io_buffer_size);
+ if (!tdgbl->mvol_io_cnt)
+ {
+ BURP_error_redirect(0, 220);
+ // msg 220 Unexpected I/O error while reading from backup file
+ }
+ tdgbl->mvol_io_ptr = tdgbl->mvol_io_buffer;
+ }
+ else
+ {
+ mvol_read(cnt, ptr);
+ }
+
+ tdgbl->mvol_cumul_count += tdgbl->mvol_io_cnt;
+ file_not_empty();
+
+ if (ptr)
+ *ptr = tdgbl->mvol_io_ptr + 1;
+ if (cnt)
+ *cnt = tdgbl->mvol_io_cnt - 1;
+
+ return *tdgbl->mvol_io_ptr;
+}
+
+
#ifndef WIN_NT
//____________________________________________________________
//
// Read a buffer's worth of data. (non-WIN_NT)
//
-int MVOL_read(int* cnt, UCHAR** ptr)
+static void mvol_read(int* cnt, UCHAR** ptr)
{
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -300,14 +342,6 @@
}
}
}
-
- tdgbl->mvol_cumul_count += tdgbl->mvol_io_cnt;
- file_not_empty();
-
- *ptr = tdgbl->mvol_io_ptr + 1;
- *cnt = tdgbl->mvol_io_cnt - 1;
-
- return *tdgbl->mvol_io_ptr;
}
@@ -316,7 +350,7 @@
//
// Read a buffer's worth of data. (WIN_NT)
//
-int MVOL_read(int* cnt, UCHAR** ptr)
+static void mvol_read(int* cnt, UCHAR** ptr)
{
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -348,14 +382,6 @@
// msg 50 unexpected end of file on backup file
}
}
-
- tdgbl->mvol_cumul_count += tdgbl->mvol_io_cnt;
- file_not_empty();
-
- *ptr = tdgbl->mvol_io_ptr + 1;
- *cnt = tdgbl->mvol_io_cnt - 1;
-
- return *tdgbl->mvol_io_ptr;
}
#endif // !WIN_NT
@@ -512,169 +538,178 @@
const ULONG size_to_write = BURP_UP_TO_BLOCK(*io_ptr - tdgbl->mvol_io_buffer);
ULONG left = size_to_write;
- for (ptr = tdgbl->mvol_io_buffer; left > 0; ptr += cnt, left -= cnt)
+ if (tdgbl->stdIoMode && tdgbl->uSvc->isService())
{
- if (tdgbl->action->act_action == ACT_backup_split)
+ tdgbl->uSvc->started();
+ tdgbl->uSvc->putBytes(tdgbl->mvol_io_buffer, left);
+ left = 0;
+ }
+ else
+ {
+ for (ptr = tdgbl->mvol_io_buffer; left > 0; ptr += cnt, left -= cnt)
{
- // Write to the current file till fil_length > 0, otherwise
- // switch to the next one
- if (tdgbl->action->act_file->fil_length == 0)
+ if (tdgbl->action->act_action == ACT_backup_split)
{
- if (tdgbl->action->act_file->fil_next)
+ // Write to the current file till fil_lingth > 0, otherwise
+ // switch to the next one
+ if (tdgbl->action->act_file->fil_length == 0)
{
- close_platf(tdgbl->file_desc);
- for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ if (tdgbl->action->act_file->fil_next)
{
- if (file->fil_fd == tdgbl->file_desc)
- file->fil_fd = INVALID_HANDLE_VALUE;
+ close_platf(tdgbl->file_desc);
+ for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ {
+ if (file->fil_fd == tdgbl->file_desc)
+ file->fil_fd = INVALID_HANDLE_VALUE;
+ }
+ tdgbl->action->act_file->fil_fd = INVALID_HANDLE_VALUE;
+ tdgbl->action->act_file = tdgbl->action->act_file->fil_next;
+ tdgbl->file_desc = tdgbl->action->act_file->fil_fd;
}
- tdgbl->action->act_file->fil_fd = INVALID_HANDLE_VALUE;
- tdgbl->action->act_file = tdgbl->action->act_file->fil_next;
- tdgbl->file_desc = tdgbl->action->act_file->fil_fd;
+ else
+ {
+ // This is a last file. Keep writing in a hope that there is
+ // enough free disk space ...
+ tdgbl->action->act_file->fil_length = MAX_LENGTH;
+ }
}
- else
- {
- // This is a last file. Keep writing in a hope that there is
- // enough free disk space ...
- tdgbl->action->act_file->fil_length = MAX_LENGTH;
- }
}
- }
- const size_t nBytesToWrite =
- (tdgbl->action->act_action == ACT_backup_split &&
- tdgbl->action->act_file->fil_length < left) ?
- tdgbl->action->act_file->fil_length : left;
+ const size_t nBytesToWrite =
+ (tdgbl->action->act_action == ACT_backup_split &&
+ tdgbl->action->act_file->fil_length < left) ?
+ tdgbl->action->act_file->fil_length : left;
#ifndef WIN_NT
- cnt = write(tdgbl->file_desc, ptr, nBytesToWrite);
+ cnt = write(tdgbl->file_desc, ptr, nBytesToWrite);
#else
- DWORD ret = 0;
- if (!WriteFile(tdgbl->file_desc, ptr, (DWORD) nBytesToWrite, &cnt, NULL))
- {
- ret = GetLastError();
- }
+ DWORD ret = 0;
+ if (!WriteFile(tdgbl->file_desc, ptr, (DWORD) nBytesToWrite, &cnt, NULL))
+ {
+ ret = GetLastError();
+ }
#endif // !WIN_NT
- tdgbl->mvol_io_buffer = tdgbl->mvol_io_data;
- if (cnt > 0)
- {
- tdgbl->mvol_cumul_count += cnt;
- file_not_empty();
- if (tdgbl->action->act_action == ACT_backup_split)
+ tdgbl->mvol_io_buffer = tdgbl->mvol_io_data;
+ if (cnt > 0)
{
- if (tdgbl->action->act_file->fil_length < left)
- tdgbl->action->act_file->fil_length = 0;
- else
- tdgbl->action->act_file->fil_length -= left;
+ tdgbl->mvol_cumul_count += cnt;
+ file_not_empty();
+ if (tdgbl->action->act_action == ACT_backup_split)
+ {
+ if (tdgbl->action->act_file->fil_length < left)
+ tdgbl->action->act_file->fil_length = 0;
+ else
+ tdgbl->action->act_file->fil_length -= left;
+ }
}
- }
- else
- {
- if (!cnt ||
+ else
+ {
+ if (!cnt ||
#ifndef WIN_NT
- errno == ENOSPC || errno == EIO || errno == ENXIO ||
- errno == EFBIG)
+ errno == ENOSPC || errno == EIO || errno == ENXIO ||
+ errno == EFBIG)
#else
- ret == ERROR_DISK_FULL || ret == ERROR_HANDLE_DISK_FULL)
+ ret == ERROR_DISK_FULL || ret == ERROR_HANDLE_DISK_FULL)
#endif // !WIN_NT
- {
- if (tdgbl->action->act_action == ACT_backup_split)
{
- // Close the current file and switch to the next one.
- // If there is no more specified files left then
- // issue an error and give up
- if (tdgbl->action->act_file->fil_next)
+ if (tdgbl->action->act_action == ACT_backup_split)
{
- close_platf(tdgbl->file_desc);
- for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ // Close the current file and switch to the next one.
+ // If there is no more specified files left then
+ // issue an error and give up
+ if (tdgbl->action->act_file->fil_next)
{
- if (file->fil_fd == tdgbl->file_desc)
- file->fil_fd = INVALID_HANDLE_VALUE;
+ close_platf(tdgbl->file_desc);
+ for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next)
+ {
+ if (file->fil_fd == tdgbl->file_desc)
+ file->fil_fd = INVALID_HANDLE_VALUE;
+ }
+
+ tdgbl->action->act_file->fil_fd = INVALID_HANDLE_VALUE;
+ BURP_print(false, 272, SafeArg() <<
+ tdgbl->action->act_file->fil_name.c_str() <<
+ tdgbl->action->act_file->fil_length <<
+ tdgbl->action->act_file->fil_next->fil_name.c_str());
+ // msg 272 Warning -- free disk space exhausted for file %s,
+ // the rest of the bytes (%d) will be written to file %s
+ tdgbl->action->act_file->fil_next->fil_length +=
+ tdgbl->action->act_file->fil_length;
+ tdgbl->action->act_file = tdgbl->action->act_file->fil_next;
+ tdgbl->file_desc = tdgbl->action->act_file->fil_fd;
}
+ else
+ {
+ BURP_error(270, true);
+ // msg 270 free disk space exhausted
+ }
+ cnt = 0;
+ continue;
+ }
- tdgbl->action->act_file->fil_fd = INVALID_HANDLE_VALUE;
- BURP_print(true, 272, SafeArg() <<
- tdgbl->action->act_file->fil_name.c_str() <<
- tdgbl->action->act_file->fil_length <<
- tdgbl->action->act_file->fil_next->fil_name.c_str());
- // msg 272 Warning -- free disk space exhausted for file %s,
- // the rest of the bytes (%d) will be written to file %s
- tdgbl->action->act_file->fil_next->fil_length +=
- tdgbl->action->act_file->fil_length;
- tdgbl->action->act_file = tdgbl->action->act_file->fil_next;
- tdgbl->file_desc = tdgbl->action->act_file->fil_fd;
- }
- else
+ if (tdgbl->uSvc->isService())
{
BURP_error(270, true);
// msg 270 free disk space exhausted
}
- cnt = 0;
- continue;
- }
- if (tdgbl->uSvc->isService())
- {
- BURP_error(270, true);
- // msg 270 free disk space exhausted
- }
+ // Note: there is an assumption here, that if header data is being
+ // written, it is really being rewritten, so at least all the
+ // header data will be written
- // Note: there is an assumption here, that if header data is being
- // written, it is really being rewritten, so at least all the
- // header data will be written
+ if (left != size_to_write)
+ {
+ // Wrote some, move remainder up in buffer.
- if (left != size_to_write)
- {
- // Wrote some, move remainder up in buffer.
-
- // NOTE: We should NOT use memcpy here. We're moving overlapped
- // data and memcpy does not guanantee the order the data
- // is moved in
- memcpy(tdgbl->mvol_io_data, ptr, left);
+ // NOTE: We should NOT use memcpy here. We're moving overlapped
+ // data and memcpy does not guanantee the order the data
+ // is moved in
+ memcpy(tdgbl->mvol_io_data, ptr, left);
+ }
+ left += tdgbl->mvol_io_data - tdgbl->mvol_io_header;
+ bool full_buffer;
+ if (left >= tdgbl->mvol_io_buffer_size)
+ full_buffer = true;
+ else
+ full_buffer = false;
+ tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_WRITE, full_buffer);
+ if (full_buffer)
+ {
+ left -= tdgbl->mvol_io_buffer_size;
+ memcpy(tdgbl->mvol_io_data,
+ tdgbl->mvol_io_header + tdgbl->mvol_io_buffer_size,
+ left);
+ tdgbl->mvol_cumul_count += tdgbl->mvol_io_buffer_size;
+ tdgbl->mvol_io_buffer = tdgbl->mvol_io_data;
+ }
+ else
+ tdgbl->mvol_io_buffer = tdgbl->mvol_io_header;
+ break;
}
- left += tdgbl->mvol_io_data - tdgbl->mvol_io_header;
- bool full_buffer;
- if (left >= tdgbl->mvol_io_buffer_size)
- full_buffer = true;
- else
- full_buffer = false;
- tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_WRITE, full_buffer);
- if (full_buffer)
+ else if (!SYSCALL_INTERRUPTED(errno))
{
- left -= tdgbl->mvol_io_buffer_size;
- memcpy(tdgbl->mvol_io_data,
- tdgbl->mvol_io_header + tdgbl->mvol_io_buffer_size,
- left);
- tdgbl->mvol_cumul_count += tdgbl->mvol_io_buffer_size;
- tdgbl->mvol_io_buffer = tdgbl->mvol_io_data;
+ BURP_error_redirect(0, 221);
+ // msg 221 Unexpected I/O error while writing to backup file
}
- else
- tdgbl->mvol_io_buffer = tdgbl->mvol_io_header;
- break;
}
- else if (!SYSCALL_INTERRUPTED(errno))
- {
- BURP_error_redirect(0, 221);
- // msg 221 Unexpected I/O error while writing to backup file
+ if (left < cnt) { // this is impossible, but...
+ cnt = left;
}
- }
- if (left < cnt) { // this is impossible, but...
- cnt = left;
- }
- } // for
+ } // for
#ifdef DEBUG
- {
- int dbg_cnt;
- if (debug_on)
{
- for (dbg_cnt = 0; dbg_cnt < cnt; dbg_cnt++)
- printf("%d,\n", *(ptr + dbg_cnt));
+ int dbg_cnt;
+ if (debug_on)
+ {
+ for (dbg_cnt = 0; dbg_cnt < cnt; dbg_cnt++)
+ printf("%d,\n", *(ptr + dbg_cnt));
+ }
}
+#endif
}
-#endif
// After the first block of first volume is written (using a default block size)
// change the block size to one that reflects the user's blocking factor. By
@@ -956,27 +991,27 @@
if (strlen(tdgbl->mvol_old_file) > 0)
{
BURP_msg_get(225, msg, SafeArg() << (tdgbl->mvol_volume_count - 1) << tdgbl->mvol_old_file);
- fprintf(term_out, msg);
+ fprintf(term_out, "%s", msg);
BURP_msg_get(226, msg);
// \tPress return to reopen that file, or type a new\n\tname
// followed by return to open a different file.\n
- fprintf(term_out, msg);
+ fprintf(term_out, "%s", msg);
}
else // First volume
{
BURP_msg_get(227, msg);
// Type a file name to open and hit return
- fprintf(term_out, msg);
+ fprintf(term_out, "%s", msg);
}
BURP_msg_get(228, msg); // " Name: "
- fprintf(term_out, msg);
+ fprintf(term_out, "%s", msg);
fflush(term_out);
if (fgets(name, length, term_in) == NULL)
{
BURP_msg_get(229, msg);
// \n\nERROR: Backup incomplete\n
- fprintf(term_out, msg);
+ fprintf(term_out, "%s", msg);
BURP_exit_local(FINI_ERROR, tdgbl);
}
@@ -1073,13 +1108,21 @@
// Headers are a version number, and a volume number
+ if (tdgbl->stdIoMode && tdgbl->uSvc->isService())
+ {
+ tdgbl->uSvc->started();
+ tdgbl->mvol_io_cnt = tdgbl->uSvc->getBytes(tdgbl->mvol_io_buffer, tdgbl->mvol_io_buffer_size);
+ }
+ else
+ {
#ifndef WIN_NT
- tdgbl->mvol_io_cnt = read(handle, tdgbl->mvol_io_buffer, tdgbl->mvol_actual_buffer_size);
+ tdgbl->mvol_io_cnt = read(handle, tdgbl->mvol_io_buffer, tdgbl->mvol_actual_buffer_size);
#else
- DWORD bytesRead = 0;
- ReadFile(handle, tdgbl->mvol_io_buffer, tdgbl->mvol_actual_buffer_size, &bytesRead, NULL);
- tdgbl->mvol_io_cnt = bytesRead;
+ DWORD bytesRead = 0;
+ ReadFile(handle, tdgbl->mvol_io_buffer, tdgbl->mvol_actual_buffer_size, &bytesRead, NULL);
+ tdgbl->mvol_io_cnt = bytesRead;
#endif
+ }
if (!tdgbl->mvol_io_cnt)
BURP_error_redirect(0, 45); // maybe there's a better message
@@ -1140,7 +1183,7 @@
{
BURP_msg_get(230, msg, SafeArg() << tdgbl->gbl_backup_start_time << buffer);
// Expected backup start time %s, found %s\n
- printf(msg);
+ printf("%s", msg);
return false;
}
break;
@@ -1174,7 +1217,7 @@
{
BURP_msg_get(231, msg, SafeArg() << tdgbl->gbl_database_file_name << buffer);
// Expected backup database %s, found %s\n
- printf(msg);
+ printf("%s", msg);
return false;
}
if (init_flag)
@@ -1203,7 +1246,7 @@
{
BURP_msg_get(232, msg, SafeArg() << tdgbl->mvol_volume_count << temp);
// Expected volume number %d, found volume %d\n
- printf(msg);
+ printf("%s", msg);
return false;
}
break;
Modified: firebird/branches/B2_5_Release/src/burp/spit.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/burp/spit.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/burp/spit.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -46,7 +46,9 @@
# include <time.h>
# endif
#endif
+//#include "../burp/burp.h"
#include "../burp/spit.h"
+#include "../burp/std_desc.h"
#include "../burp/burpswi.h"
#ifdef HAVE_UNISTD_H
@@ -61,6 +63,53 @@
static const int mode_write = O_WRONLY | O_CREAT;
static const int mask = 0666;
+static DESC open_platf(const char* name, int writeFlag)
+{
+#ifdef WIN_NT
+ return CreateFile(name, writeFlag ? GENERIC_WRITE : GENERIC_READ, 0, NULL,
+ writeFlag ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+#else
+ return open(name, writeFlag ? mode_write : mode_read, mask);
+#endif
+}
+
+static int read_platf(DESC file, void* buf, int count)
+{
+#ifdef WIN_NT
+ DWORD act;
+ if (!ReadFile(file, buf, count, &act, NULL))
+ {
+ return -1;
+ }
+ return act;
+#else
+ return read(file, buf, count);
+#endif
+}
+
+static int write_platf(DESC file, const void* buf, int count)
+{
+#ifdef WIN_NT
+ DWORD act;
+ if (!WriteFile(file, buf, count, &act, NULL))
+ {
+ return -1;
+ }
+ return act;
+#else
+ return write(file, buf, count);
+#endif
+}
+
+static void close_platf(DESC file)
+{
+#ifdef WIN_NT
+ CloseHandle(file);
+#else
+ close(file);
+#endif
+}
+
// Definitions for GSPLIT
enum gsplit_option
{
@@ -279,7 +328,7 @@
switch (sw_replace)
{
case IN_SW_SPIT_SP:
- input_file_desc = GBAK_STDIN_DESC;
+ input_file_desc = GBAK_STDIN_DESC();
ret_cd = gen_multy_bakup_files(file_list, input_file_desc, file_num);
if (ret_cd == FB_FAILURE) {
fprintf(stderr, "%s: progam fails to generate multi-volumn back-up files\n", prog_name);
@@ -598,8 +647,8 @@
file_size = fl_ptr->b_fil_size - header_rec_len;
file_name = fl_ptr->b_fil_name;
- output_fl_desc = open(file_name, mode_write, mask);
- if (output_fl_desc == -1) {
+ output_fl_desc = open_platf(file_name, 1);
+ if (output_fl_desc == INVALID_HANDLE_VALUE) {
free(io_buffer);
fprintf(stderr, "can not open back up file %s\n", file_name);
return FB_FAILURE;
@@ -665,8 +714,8 @@
file_size = fl_ptr->b_fil_size - header_rec_len;
file_name = fl_ptr->b_fil_name;
- output_fl_desc = open(file_name, mode_write, mask);
- if (output_fl_desc == -1) {
+ output_fl_desc = open_platf(file_name, 1);
+ if (output_fl_desc == INVALID_HANDLE_VALUE) {
free(io_buffer);
fprintf(stderr, "can not open back up file %s\n", file_name);
return FB_FAILURE;
@@ -767,21 +816,21 @@
if (*byte_read + io_size > file_size) {
last_read_size = (SLONG) (file_size - *byte_read);
- read_cnt = read(input_file_desc, *io_buffer, last_read_size);
+ read_cnt = read_platf(input_file_desc, *io_buffer, last_read_size);
}
else
- read_cnt = read(input_file_desc, *io_buffer, io_size);
+ read_cnt = read_platf(input_file_desc, *io_buffer, io_size);
switch (read_cnt)
{
case 0: // no more data to be read
- close(output_fl_desc);
+ close_platf(output_fl_desc);
*end_of_input = true;
*byte_read = *byte_read + read_cnt;
return FB_SUCCESS;
case -1: // read failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
fprintf(stderr, "fail to read input from stdin, errno = %d\n", errno);
return FB_FAILURE;
@@ -790,12 +839,12 @@
break;
}
- const SLONG write_cnt = write(output_fl_desc, *io_buffer, read_cnt);
+ const SLONG write_cnt = write_platf(output_fl_desc, *io_buffer, read_cnt);
switch (write_cnt)
{
case -1: // write failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
return FB_FAILURE;
default:
@@ -803,7 +852,7 @@
return FB_SUCCESS;
// write less data than it reads in
- close(output_fl_desc);
+ close_platf(output_fl_desc);
*byte_write = write_cnt;
return FILE_IS_FULL;
}
@@ -832,17 +881,17 @@
*********************************************************************
*/
- const SLONG read_cnt = read(input_file_desc, *io_buffer, io_size);
+ const SLONG read_cnt = read_platf(input_file_desc, *io_buffer, io_size);
switch (read_cnt)
{
case 0: // no more data to be read
- close(output_fl_desc);
+ close_platf(output_fl_desc);
*end_of_input = true;
return FB_SUCCESS;
case -1: // read failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
fprintf(stderr, "problem when reading input file, errno = %d\n", errno);
return FB_FAILURE;
@@ -850,12 +899,12 @@
break;
}
- const SLONG write_cnt = write(output_fl_desc, *io_buffer, read_cnt);
+ const SLONG write_cnt = write_platf(output_fl_desc, *io_buffer, read_cnt);
switch (write_cnt)
{
case -1: // write failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
return FB_FAILURE;
default:
@@ -863,7 +912,7 @@
return FB_SUCCESS;
fprintf(stderr, "There is no enough space to write to back up file %s\n", file_name);
- close(output_fl_desc);
+ close_platf(output_fl_desc);
return FB_FAILURE;
}
}
@@ -888,7 +937,7 @@
*********************************************************************
*/
- FILE_DESC output_fl_desc = GBAK_STDOUT_DESC;
+ FILE_DESC output_fl_desc = GBAK_STDOUT_DESC();
// See comment near the beginning of gen_multy_bakup_files() as it
// also applies to read_and_write_for_join().
@@ -946,16 +995,16 @@
TEXT num_arr[5], total_arr[5];
header_rec hdr_rec;
- FILE_DESC input_fl_desc = open(file_name, mode_read);
+ FILE_DESC input_fl_desc = open_platf(file_name, mode_read);
- if (input_fl_desc == -1) {
+ if (input_fl_desc == INVALID_HANDLE_VALUE) {
fprintf(stderr, "can not open input file %s\n", file_name);
return FB_FAILURE;
}
- int read_cnt = read(input_fl_desc, *io_buffer, header_rec_len);
+ int read_cnt = read_platf(input_fl_desc, *io_buffer, header_rec_len);
if (read_cnt != static_cast<int>(header_rec_len)) {
- close(input_fl_desc);
+ close_platf(input_fl_desc);
fprintf(stderr, "progam fails to read gsplit header record in back-up file%s\n", file_name);
return FB_FAILURE;
}
@@ -963,7 +1012,7 @@
const TEXT* char_ptr1 = reinterpret_cast<char*>(*io_buffer);
SLONG ret_cd = strncmp(char_ptr1, header_rec_name, sizeof(hdr_rec.name) - 1);
if (ret_cd != 0) {
- close(input_fl_desc);
+ close_platf(input_fl_desc);
fprintf(stderr, "gsplit: expected GSPLIT description record\n");
fprintf(stderr, "gsplit: Exiting before completion due to errors\n");
return FB_FAILURE;
@@ -991,13 +1040,13 @@
}
if ((num_int != cnt) || (num_int > *total_int)) {
- close(input_fl_desc);
+ close_platf(input_fl_desc);
fprintf(stderr, "gsplit: join backup file is out of sequence\n");
fprintf(stderr, "gsplit: Exiting before completion due to errors\n");
return FB_FAILURE;
}
- read_cnt = read(input_fl_desc, *io_buffer, IO_BUFFER_SIZE);
+ read_cnt = read_platf(input_fl_desc, *io_buffer, IO_BUFFER_SIZE);
while (true)
@@ -1005,23 +1054,23 @@
switch (read_cnt)
{
case 0: // no more data to be read
- close(input_fl_desc);
+ close_platf(input_fl_desc);
return FB_SUCCESS;
case -1: // read failed
- close(input_fl_desc);
+ close_platf(input_fl_desc);
return FB_FAILURE;
default: // this is the last read
break;
}
- SLONG write_cnt = write(output_fl_desc, *io_buffer, read_cnt);
+ SLONG write_cnt = write_platf(output_fl_desc, *io_buffer, read_cnt);
switch (write_cnt)
{
case -1: // write failed
- close(input_fl_desc);
+ close_platf(input_fl_desc);
return FB_FAILURE;
default:
@@ -1029,7 +1078,7 @@
break;
}
- read_cnt = read(input_fl_desc, *io_buffer, IO_BUFFER_SIZE);
+ read_cnt = read_platf(input_fl_desc, *io_buffer, IO_BUFFER_SIZE);
} // end of while (true) loop
}
@@ -1114,11 +1163,11 @@
ret_cd = set_hdr_str(header_str, file_name, pos, strlen(file_name));
SLONG end, indx;
- SLONG write_cnt = write(output_fl_desc, header_str, header_rec_len);
+ SLONG write_cnt = write_platf(output_fl_desc, header_str, header_rec_len);
switch (write_cnt)
{
case -1: // write failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
return FB_FAILURE;
default:
@@ -1166,14 +1215,14 @@
SLONG write_cnt;
if (file_size > remaining_io_len)
- write_cnt = write(output_fl_desc, remaining_io, remaining_io_len);
+ write_cnt = write_platf(output_fl_desc, remaining_io, remaining_io_len);
else // file_size <= remaining_io_len
- write_cnt = write(output_fl_desc, remaining_io, (unsigned int) file_size);
+ write_cnt = write_platf(output_fl_desc, remaining_io, (unsigned int) file_size);
switch (write_cnt)
{
case -1: // write failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
*flush_done = false;
return FB_FAILURE;
@@ -1181,7 +1230,7 @@
if (write_cnt == remaining_io_len) // write ok
*flush_done = true;
else { // could not write out all remaining data
- close(output_fl_desc);
+ close_platf(output_fl_desc);
*flush_done = false;
}
*byte_write = write_cnt;
@@ -1207,18 +1256,18 @@
*********************************************************************
*/
- SLONG write_cnt = write(output_fl_desc, remaining_io, remaining_io_len);
+ SLONG write_cnt = write_platf(output_fl_desc, remaining_io, remaining_io_len);
switch (write_cnt)
{
case -1: // write failed
- close(output_fl_desc);
+ close_platf(output_fl_desc);
return FB_FAILURE;
default:
if (write_cnt == remaining_io_len) // write ok
return FB_SUCCESS;
- close(output_fl_desc);
+ close_platf(output_fl_desc);
return FB_FAILURE;
}
}
Modified: firebird/branches/B2_5_Release/src/burp/spit.h
===================================================================
--- firebird/branches/B2_5_Release/src/burp/spit.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/burp/spit.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -42,8 +42,3 @@
const int MIN_FILE_SIZE = M_BYTES;
const char NEW_LINE = '\n';
const char TERMINAL = '\0';
-
-typedef int FILE_DESC;
-
-const FILE_DESC GBAK_STDIN_DESC = 0; // standard input file descriptor
-const FILE_DESC GBAK_STDOUT_DESC = 1; // standard output file descriptor
Modified: firebird/branches/B2_5_Release/src/burp/std_desc.h
===================================================================
--- firebird/branches/B2_5_Release/src/burp/std_desc.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/burp/std_desc.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -61,4 +61,6 @@
#endif //WIN_NT
+typedef DESC FILE_DESC;
+
#endif //GBAK_STD_DESC_H
Modified: firebird/branches/B2_5_Release/src/common/UtilSvc.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/common/UtilSvc.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/common/UtilSvc.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -127,6 +127,7 @@
virtual void putSLong(char, SLONG) { }
virtual void putChar(char, char) { }
virtual void putBytes(const UCHAR*, size_t) { }
+ virtual ULONG getBytes(UCHAR*, ULONG) { return 0; }
virtual void setServiceStatus(const ISC_STATUS*) { }
virtual void setServiceStatus(const USHORT, const USHORT, const MsgFormat::SafeArg&) { }
virtual const ISC_STATUS* getStatus() { return 0; }
Modified: firebird/branches/B2_5_Release/src/common/UtilSvc.h
===================================================================
--- firebird/branches/B2_5_Release/src/common/UtilSvc.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/common/UtilSvc.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -63,6 +63,7 @@
virtual void putSLong(char, SLONG) = 0;
virtual void putChar(char, char) = 0;
virtual void putBytes(const UCHAR*, size_t) = 0;
+ virtual ULONG getBytes(UCHAR*, ULONG) = 0;
virtual void setServiceStatus(const ISC_STATUS*) = 0;
virtual void setServiceStatus(const USHORT, const USHORT, const MsgFormat::SafeArg&) = 0;
virtual const ISC_STATUS* getStatus() = 0;
@@ -71,10 +72,6 @@
virtual void hidePasswd(ArgvType&, int) = 0;
virtual void getAddressPath(Firebird::ClumpletWriter& dpb) = 0;
virtual bool finished() = 0;
- void setDataMode(bool value)
- {
- usvcDataMode = value;
- }
virtual ~UtilSvc() { }
@@ -100,6 +97,11 @@
switches += ' ';
}
+ void setDataMode(bool value)
+ {
+ usvcDataMode = value;
+ }
+
public:
ArgvType argv;
bool usvcDataMode;
Modified: firebird/branches/B2_5_Release/src/include/consts_pub.h
===================================================================
--- firebird/branches/B2_5_Release/src/include/consts_pub.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/include/consts_pub.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -318,6 +318,7 @@
#define isc_info_svc_limbo_trans 66 /* Retrieve the limbo transactions */
#define isc_info_svc_running 67 /* Checks to see if a service is running on an attachment */
#define isc_info_svc_get_users 68 /* Returns the user information from isc_action_svc_display_users */
+#define isc_info_svc_stdin 78 /* Returns size of data, needed as stdin for service */
/******************************************************
* Parameters for isc_action_{add|del|mod|disp)_user *
Modified: firebird/branches/B2_5_Release/src/include/gen/msgs.h
===================================================================
--- firebird/branches/B2_5_Release/src/include/gen/msgs.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/include/gen/msgs.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -852,7 +852,7 @@
{336331015, "file @1 out of sequence"}, /* 825, gbak_file_outof_sequence */
{336331016, "can't join -- one of the files missing"}, /* 826, gbak_join_file_missing */
{336331017, " standard input is not supported when using join operation"}, /* 827, gbak_stdin_not_supptd */
- {336331018, "standard output is not supported when using split operation"}, /* 828, gbak_stdout_not_supptd */
+ {336331018, "standard output is not supported when using split operation or in verbose mode"}, /* 828, gbak_stdout_not_supptd */
{336331019, "backup file @1 might be corrupt"}, /* 829, gbak_bkup_corrupt */
{336331020, "database file specification missing"}, /* 830, gbak_unk_db_file_spec */
{336331021, "can't write a header record to file @1"}, /* 831, gbak_hdr_write_failed */
Modified: firebird/branches/B2_5_Release/src/jrd/svc.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/jrd/svc.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/jrd/svc.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -115,6 +115,7 @@
const int GET_LINE = 1;
const int GET_EOF = 2;
const int GET_BINARY = 4;
+const int GET_ONCE = 8;
const char* const SPB_SEC_USERNAME = "isc_spb_sec_username";
@@ -448,6 +449,7 @@
void Service::finish()
{
+ svc_sem_full.release();
finish(SVC_finished);
}
@@ -657,7 +659,7 @@
bool Service::ck_space_for_numeric(UCHAR*& info, const UCHAR* const end)
{
if ((info + 1 + sizeof(ULONG)) > end)
- {
+ {
if (info < end)
*info++ = isc_info_truncated;
return false;
@@ -792,7 +794,9 @@
svc_trusted_login(getPool()), svc_trusted_role(false), svc_uses_security_database(false),
svc_switches(getPool()), svc_perm_sw(getPool()), svc_address_path(getPool()),
svc_network_protocol(getPool()), svc_remote_address(getPool()), svc_remote_process(getPool()),
- svc_remote_pid(0), svc_current_guard(NULL)
+ svc_remote_pid(0), svc_current_guard(NULL),
+ svc_stdin_size_requested(0), svc_stdin_buffer(NULL), svc_stdin_size_preload(0),
+ svc_stdin_preload_requested(0), svc_stdin_user_size(0)
{
svc_trace_manager = NULL;
memset(svc_status, 0, sizeof svc_status);
@@ -1095,7 +1099,7 @@
AllServices& all(allServices);
ULONG cnt = 0;
-
+
// don't count already detached services
for (size_t i = 0; i < all.getCount(); i++)
{
@@ -1135,14 +1139,16 @@
AllServices& all(allServices);
unsigned int pos;
-
+
// signal once for every still running service
for (pos = 0; pos < all.getCount(); pos++)
{
if (all[pos]->svc_flags & SVC_thd_running)
all[pos]->svc_detach_sem.release();
+ if (all[pos]->svc_stdin_size_requested)
+ all[pos]->svc_stdin_semaphore.release();
}
-
+
for (pos = 0; pos < all.getCount(); )
{
if (all[pos]->svc_flags & SVC_thd_running)
@@ -1172,18 +1178,22 @@
UCHAR item;
UCHAR buffer[MAXPATHLEN];
USHORT l, length, version, get_flags;
+ UCHAR* stdin_request_notification = NULL;
ThreadIdHolder holdId(svc_thread_strings);
// Setup the status vector
Arg::StatusVector status;
+ ULONG requestFromPut = 0;
+
try
{
// Process the send portion of the query first.
USHORT timeout = 0;
const UCHAR* items = send_items;
const UCHAR* const end_items = items + send_item_length;
+
while (items < end_items && *items != isc_info_end)
{
switch ((item = *items++))
@@ -1199,10 +1209,10 @@
switch (item)
{
case isc_info_svc_line:
- put(items, l);
+ requestFromPut = put(items, l);
break;
case isc_info_svc_message:
- put(items - 3, l + 3);
+ //put(items - 3, l + 3);
break;
case isc_info_svc_timeout:
timeout = (USHORT) gds__vax_integer(items, l);
@@ -1460,6 +1470,21 @@
} // scope
break;
+ case isc_info_svc_stdin:
+ // Check - is stdin data required for server
+ if (!ck_space_for_numeric(info, end))
+ {
+ return 0;
+ }
+ *info++ = item;
+ if (!stdin_request_notification)
+ {
+ stdin_request_notification = info;
+ }
+ ADD_SPB_NUMERIC(info, 0);
+
+ break;
+
case isc_info_svc_user_dbpath:
if (svc_user_flag & SVC_user_dba)
{
@@ -1482,7 +1507,7 @@
*info++ = isc_info_truncated;
break;
}
- put(&item, 1);
+ //put(&item, 1);
get(&item, 1, GET_BINARY, 0, &length);
get(buffer, 2, GET_BINARY, 0, &length);
l = (USHORT) gds__vax_integer(buffer, 2);
@@ -1523,7 +1548,7 @@
break;
case isc_info_svc_total_length:
- put(&item, 1);
+ //put(&item, 1);
get(&item, 1, GET_BINARY, 0, &length);
get(buffer, 2, GET_BINARY, 0, &length);
l = (USHORT) gds__vax_integer(buffer, 2);
@@ -1555,6 +1580,11 @@
break;
}
+ if (requestFromPut)
+ {
+ get_flags |= GET_ONCE;
+ }
+
get(info + 3, end - (info + 5), get_flags, timeout, &length);
/* If the read timed out, return the data, if any, & a timeout
@@ -1570,7 +1600,7 @@
{
*info++ = isc_info_svc_timeout;
}
- else
+ else //if (!svc_stdin_size_requested)
{
if (!length && !(svc_flags & SVC_finished))
{
@@ -1600,6 +1630,8 @@
const SLONG number = info - start_info;
fb_assert(number > 0);
memmove(start_info + 7, start_info, number);
+ if (stdin_request_notification)
+ stdin_request_notification += 7;
USHORT length2 = INF_convert(number, buffer);
fb_assert(length2 == 4); // We only accept SLONG
INF_put_item(isc_info_length, length2, buffer, start_info, end, true);
@@ -1612,6 +1644,23 @@
recv_item_length, recv_items, res_successful);
}
+ if (!requestFromPut)
+ {
+ requestFromPut = svc_stdin_size_requested;
+ }
+
+ if (requestFromPut)
+ {
+ if (stdin_request_notification)
+ {
+ ADD_SPB_NUMERIC(stdin_request_notification, requestFromPut);
+ }
+ else
+ {
+ (Arg::Gds(isc_random) << "No request from user for stdin data").raise();
+ }
+ }
+
if (status.hasData())
{
status.raise();
@@ -1699,10 +1748,10 @@
switch (item)
{
case isc_info_svc_line:
- put(items, l);
+ //put(items, l);
break;
case isc_info_svc_message:
- put(items - 3, l + 3);
+ //put(items - 3, l + 3);
break;
case isc_info_svc_timeout:
timeout = (USHORT) gds__vax_integer(items, l);
@@ -1931,7 +1980,7 @@
*info++ = isc_info_truncated;
break;
}
- put(&item, 1);
+ //put(&item, 1);
get(&item, 1, GET_BINARY, 0, &length);
get(buffer, 2, GET_BINARY, 0, &length);
l = (USHORT) gds__vax_integer(buffer, 2);
@@ -1974,7 +2023,7 @@
break;
case isc_info_svc_total_length:
- put(&item, 1);
+ //put(&item, 1);
get(&item, 1, GET_BINARY, 0, &length);
get(buffer, 2, GET_BINARY, 0, &length);
l = (USHORT) gds__vax_integer(buffer, 2);
@@ -2373,19 +2422,29 @@
void Service::enqueue(const UCHAR* s, ULONG len)
{
+ static int transferCount = 0;
+
if (checkForShutdown() || (svc_flags & SVC_detached))
{
+ svc_sem_full.release();
return;
}
while (len)
{
// Wait for space in buffer
+ bool flagFirst = true;
while (full())
{
- THREAD_SLEEP(1);
+ if (flagFirst)
+ {
+ svc_sem_full.release();
+ flagFirst = false;
+ }
+ svc_sem_empty.tryEnter(1, 0);
if (checkForShutdown() || (svc_flags & SVC_detached))
{
+ svc_sem_full.release();
return;
}
}
@@ -2403,10 +2462,12 @@
}
memcpy(&svc_stdout[svc_stdout_tail], s, cnt);
+ transferCount += cnt;
svc_stdout_tail = add_val(svc_stdout_tail, cnt);
s += cnt;
len -= cnt;
}
+ svc_sem_full.release();
}
@@ -2427,6 +2488,7 @@
svc_flags &= ~SVC_timeout;
}
+ bool flagFirst = true;
while (length)
{
if ((empty() && (svc_flags & SVC_finished)) || checkForShutdown())
@@ -2436,7 +2498,24 @@
if (empty())
{
- THREAD_SLEEP(1);
+ if (svc_stdin_size_requested && (!(flags & GET_BINARY)))
+ {
+ // service needs data from user - notify him
+ break;
+ }
+
+ if (flagFirst)
+ {
+ svc_sem_empty.release();
+ flagFirst = false;
+ }
+
+ if (flags & GET_ONCE)
+ {
+ break;
+ }
+
+ svc_sem_full.tryEnter(1, 0);
}
#ifdef HAVE_GETTIMEOFDAY
GETTIMEOFDAY(&end_time);
@@ -2456,6 +2535,7 @@
while (head != svc_stdout_tail && length > 0)
{
+ flagFirst = true;
const UCHAR ch = svc_stdout[head];
head = add_one(head);
length--;
@@ -2476,15 +2556,103 @@
svc_stdout_head = head;
}
+ svc_sem_empty.release();
}
-void Service::put(const UCHAR* /*buffer*/, USHORT /*length*/)
+ULONG Service::put(const UCHAR* buffer, ULONG length)
{
- // Nothing
+ MutexLockGuard guard(svc_stdin_mutex);
+
+ // check length correctness
+ if (length > svc_stdin_size_requested && length > svc_stdin_preload_requested)
+ {
+ (Arg::Gds(isc_random) << "Size of data is more than requested").raise();
+ }
+
+ if (svc_stdin_size_requested) // service waits for data from us
+ {
+ svc_stdin_user_size = MIN(length, svc_stdin_size_requested);
+ memcpy(svc_stdin_buffer, buffer, svc_stdin_user_size);
+ // reset satisfied request
+ ULONG blockSize = svc_stdin_size_requested;
+ svc_stdin_size_requested = 0;
+ // let data be used
+ svc_stdin_semaphore.release();
+
+ if (length == 0)
+ {
+ return 0;
+ }
+
+ // reset used block of data
+ length -= svc_stdin_user_size;
+ buffer += svc_stdin_user_size;
+
+ if (length == 0) // ask user to preload next block of data
+ {
+ if (!svc_stdin_preload)
+ {
+ svc_stdin_preload.reset(FB_NEW(getPool()) UCHAR[PRELOAD_BUFFER_SIZE]);
+ }
+
+ svc_stdin_preload_requested = MIN(blockSize, PRELOAD_BUFFER_SIZE);
+ return svc_stdin_preload_requested;
+ }
+ }
+
+ // Store data in preload buffer
+ fb_assert(length <= PRELOAD_BUFFER_SIZE);
+ fb_assert(length <= svc_stdin_preload_requested);
+ fb_assert(svc_stdin_size_preload == 0);
+
+ memcpy(svc_stdin_preload, buffer, length);
+ svc_stdin_size_preload = length;
+ return 0;
}
+ULONG Service::getBytes(UCHAR* buffer, ULONG size)
+{
+ { // Guard scope
+ MutexLockGuard guard(svc_stdin_mutex);
+
+ if (svc_flags & SVC_detached) // no more data for this service please
+ {
+ return 0;
+ }
+
+ if (svc_stdin_size_preload != 0) // use data, preloaded by user
+ {
+ // Use data from preload buffer
+ size = MIN(size, svc_stdin_size_preload);
+ memcpy(buffer, svc_stdin_preload, size);
+ if (size < svc_stdin_size_preload)
+ {
+ // not good, client should not request so small block
+ svc_stdin_size_preload -= size;
+ memmove(svc_stdin_preload, svc_stdin_preload + size, svc_stdin_size_preload);
+ }
+ else
+ {
+ svc_stdin_size_preload = 0;
+ }
+ return size;
+ }
+
+ // Request new data portion
+ svc_stdin_size_requested = size;
+ svc_stdin_buffer = buffer;
+ // Wakeup Service::query() if it waits for data from service
+ svc_sem_full.release();
+ }
+
+ // Wait for data from client
+ svc_stdin_semaphore.enter();
+ return svc_stdin_user_size;
+}
+
+
void Service::finish(USHORT flag)
{
if (flag == SVC_finished || flag == SVC_detached)
@@ -2501,8 +2669,26 @@
delete this;
return;
}
+
+ if (svc_flags & SVC_detached)
+ {
+ svc_sem_empty.release();
+
+ // if service waits for data from us - return EOF
+ { // guard scope
+ MutexLockGuard guard(svc_stdin_mutex);
+
+ if (svc_stdin_size_requested)
+ {
+ svc_stdin_user_size = 0;
+ svc_stdin_semaphore.release();
+ }
+ }
+ }
+
if (svc_flags & SVC_finished)
{
+ svc_sem_full.release();
svc_flags &= ~SVC_thd_running;
}
else
Modified: firebird/branches/B2_5_Release/src/jrd/svc.h
===================================================================
--- firebird/branches/B2_5_Release/src/jrd/svc.h 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/jrd/svc.h 2012-06-20 11:56:36 UTC (rev 54644)
@@ -36,7 +36,18 @@
#include "../common/classes/array.h"
#include "../common/classes/SafeArg.h"
#include "../common/UtilSvc.h"
+#include "../burp/spit.h"
+#ifndef IO_BUFFER_SIZE
+#ifdef BUFSIZ
+const int SVC_IO_BUFFER_SIZE = (16 * (BUFSIZ));
+#else // BUFSIZ
+const int SVC_IO_BUFFER_SIZE = (16 * (1024));
+#endif // BUFSIZ
+#else // IO_BUFFER_SIZE
+const int SVC_IO_BUFFER_SIZE = (16 * (IO_BUFFER_SIZE));
+#endif // IO_BUFFER_SIZE
+
// forward decl.
struct serv_entry;
namespace Firebird {
@@ -115,6 +126,8 @@
virtual void putChar(char tag, char val);
// put raw bytes to svc_stdout
virtual void putBytes(const UCHAR*, size_t);
+ // get raw bytes from svc_stdin
+ virtual ULONG getBytes(UCHAR*, ULONG);
// append status_vector to service's status
virtual void setServiceStatus(const ISC_STATUS* status_vector);
// append error message to service's status
@@ -211,8 +224,9 @@
bool checkForShutdown();
// Transfer data from svc_stdout into buffer
void get(UCHAR* buffer, USHORT length, USHORT flags, USHORT timeout, USHORT* return_length);
- // Designed to send output to a service - does nothing.
- void put(const UCHAR* buffer, USHORT length);
+ // Sends stdin for a service
+ // Returns number of bytes service wants more
+ ULONG put(const UCHAR* buffer, ULONG length);
// Increment circular buffer pointer
static ULONG add_one(ULONG i);
@@ -288,6 +302,8 @@
private:
StatusStringsHelper svc_thread_strings;
+ Firebird::Semaphore svc_sem_empty, svc_sem_full;
+
//Service existence guard
class ExistenceGuard
{
@@ -302,6 +318,23 @@
friend class ExistenceGuard;
Firebird::Mutex svc_existence_lock;
ExistenceGuard* svc_current_guard;
+
+ // Data pipe from client to service
+ Firebird::Semaphore svc_stdin_semaphore;
+ Firebird::Mutex svc_stdin_mutex;
+ // Size of data, requested by service (set in getBytes, reset in put)
+ ULONG svc_stdin_size_requested;
+ // Buffer passed by service
+ UCHAR* svc_stdin_buffer;
+ // Size of data, preloaded by user (set in put, reset in getBytes)
+ ULONG svc_stdin_size_preload;
+ // Buffer for datam preloaded by user
+ Firebird::AutoPtr<UCHAR> svc_stdin_preload;
+ // Size of data, requested from user to preload (set in getBytes)
+ ULONG svc_stdin_preload_requested;
+ // Size of data, placed into svc_stdin_buffer (set in put)
+ ULONG svc_stdin_user_size;
+ static const ULONG PRELOAD_BUFFER_SIZE = SVC_IO_BUFFER_SIZE;
};
} //namespace Jrd
Modified: firebird/branches/B2_5_Release/src/lock/lock.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/lock/lock.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/lock/lock.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -103,7 +103,7 @@
#endif
#ifdef DEV_BUILD
-#define VALIDATE_LOCK_TABLE
+//#define VALIDATE_LOCK_TABLE
#endif
#ifdef DEV_BUILD
Modified: firebird/branches/B2_5_Release/src/msgs/messages2.sql
===================================================================
--- firebird/branches/B2_5_Release/src/msgs/messages2.sql 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/msgs/messages2.sql 2012-06-20 11:56:36 UTC (rev 54644)
@@ -2432,7 +2432,7 @@
('gbak_file_outof_sequence', 'open_files', 'burp.c', NULL, 12, 263, NULL, 'file @1 out of sequence', NULL, NULL);
('gbak_join_file_missing', 'open_files', 'burp.c', NULL, 12, 264, NULL, 'can''t join -- one of the files missing', NULL, NULL);
('gbak_stdin_not_supptd', 'open_files', 'burp.c', NULL, 12, 265, NULL, ' standard input is not supported when using join operation', NULL, NULL);
-('gbak_stdout_not_supptd', 'open_files', 'burp.c', NULL, 12, 266, NULL, 'standard output is not supported when using split operation', NULL, NULL);
+('gbak_stdout_not_supptd', 'open_files', 'burp.c', NULL, 12, 266, NULL, 'standard output is not supported when using split operation or in verbose mode', NULL, NULL);
('gbak_bkup_corrupt', 'open_files', 'burp.c', NULL, 12, 267, NULL, 'backup file @1 might be corrupt', NULL, NULL);
('gbak_unk_db_file_spec', 'open_files', 'burp.c', NULL, 12, 268, NULL, 'database file specification missing', NULL, NULL);
('gbak_hdr_write_failed', 'MVOL_init_write', 'mvol.c', NULL, 12, 269, NULL, 'can''t write a header record to file @1', NULL, NULL);
Modified: firebird/branches/B2_5_Release/src/utilities/fbsvcmgr.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/utilities/fbsvcmgr.cpp 2012-06-20 11:47:30 UTC (rev 54643)
+++ firebird/branches/B2_5_Release/src/utilities/fbsvcmgr.cpp 2012-06-20 11:56:36 UTC (rev 54644)
@@ -40,6 +40,7 @@
#include "../common/utils_proto.h"
#include "../common/classes/MsgPrint.h"
#include "../jrd/license.h"
+#include "../burp/std_desc.h"
using namespace Firebird;
@@ -475,7 +476,7 @@
const SvcSwitches actionSwitch[] =
{
- {"action_backup", putSingleTag, backupOptions, isc_action_svc_backup, isc_info_svc_line},
+ {"action_backup", putSingleTag, backupOptions, isc_action_svc_backup, isc_info_svc_to_eof},
{"action_restore", putSingleTag, restoreOptions, isc_action_svc_restore, isc_info_svc_line},
{"action_properties", putSingleTag, propertiesOptions, isc_action_svc_properties, 0},
{"action_repair", putSingleTag, repairOptions, isc_action_svc_repair, 0},
@@ -527,9 +528,23 @@
bool printData(const char*& p)
{
+ static DESC binout = INVALID_HANDLE_VALUE;
+ if (binout == INVALID_HANDLE_VALUE)
+ {
+ binout = GBAK_STDOUT_DESC();
+ }
+
string s;
bool rc = getLine(s, p);
- printf ("%s", s.c_str());
+ if (rc)
+ {
+#ifdef WIN_NT
+ DWORD cnt;
+ WriteFile(binout, s.c_str(), s.length(), &cnt, NULL);
+#else
+ write(binout, s.c_str(), s.length());
+#endif
+ }
return rc;
}
@@ -599,12 +614,14 @@
}
};
-bool printInfo(const char* p, UserPrint& up)
+bool printInfo(const char* p, size_t pSize, UserPrint& up, ULONG& stdinRq)
{
bool ret = false;
bool ignoreTruncation = false;
+ stdinRq = 0;
+ const char* const end = p + pSize;
- while (*p != isc_info_end)
+ while (p < end && *p != isc_info_end)
{
switch (*p++)
{
@@ -759,9 +776,10 @@
case isc_info_truncated:
if (!ignoreTruncation)
{
- printf("%s\n", getMessage(18).c_str());
- return false;
+ printf("\n%s\n", getMessage(18).c_str());
}
+ fflush(stdout);
+ ret = true;
break;
case isc_info_svc_timeout:
@@ -769,12 +787,24 @@
ret = true;
break;
+ case isc_info_svc_stdin:
+ stdinRq = getNumeric(p);
+ if (stdinRq > 0)
+ {
+ ret = true;
+ }
+ break;
+
default:
status_exception::raise(Arg::Gds(isc_fbsvcmgr_query_err) <<
Arg::Num(static_cast<unsigned char>(p[-1])));
+#ifdef DEV_BUILD
+ abort();
+#endif
}
}
+ fflush(stdout);
return ret;
}
@@ -916,6 +946,8 @@
if (spbItems.getBufferLength() > 0)
{
+ spbItems.insertTag(isc_info_svc_stdin);
+
// use one second timeout to poll service
char send[16];
char* p = send;
@@ -925,10 +957,53 @@
*p++ = isc_info_end;
char results[maxbuf];
- UserPrint up;
+ UserPrint uPrint;
+ ULONG stdinRequest = 0;
+ Array<char> stdinBuffer;
do
{
- if (isc_service_query(status, &svc_handle, 0, p - send, send,
+ char *sendBlock = send;
+ USHORT sendSize = p - send;
+ if (stdinRequest)
+ {
+ --sendSize;
+ size_t len = sendSize;
+ len += (1 + 2 + stdinRequest);
+ if (len > MAX_USHORT - 1)
+ {
+ len = MAX_USHORT - 1;
+ stdinRequest = len - (1 + 2) - sendSize;
+ }
+ sendBlock = stdinBuffer.getBuffer(len + 1);
+ memcpy(sendBlock, send, sendSize);
+
+ static DESC binIn = INVALID_HANDLE_VALUE;
+ if (binIn == INVALID_HANDLE_VALUE)
+ {
+ binIn = GBAK_STDIN_DESC();
+ }
+
+#ifdef WIN_NT
+ DWORD n;
+ if (!ReadFile(binIn, &sendBlock[sendSize + 1 + 2], stdinRequest, &n, NULL))
+#else
+ int n = read(binIn, &sendBlock[sendSize + 1 + 2], stdinRequest);
+ if (n < 0)
+#endif
+ {
+ perror("stdin");
+ break;
+ }
+ stdinRequest = n;
+ sendBlock[sendSize] = isc_info_svc_line;
+ sendBlock[sendSize + 1] = stdinRequest;
+ sendBlock[sendSize + 2] = stdinRequest >> 8;
+ sendBlock [sendSize + 1 + 2 + stdinRequest] = isc_info_end;
+ sendSize += (1 + 2 + stdinRequest + 1);
+
+ stdinRequest = 0;
+ }
+ if (isc_service_query(status, &svc_handle, 0, sendSize, sendBlock,
static_cast<USHORT>(spbItems.getBufferLength()),
reinterpret_cast<const char*>(spbItems.getBuffer()),
sizeof(results), results))
@@ -937,10 +1012,14 @@
isc_service_detach(status, &svc_handle);
return 1;
}
- } while (printInfo(results, up) && !terminated);
+ } while (printInfo(results, sizeof(results), uPrint, stdinRequest) && !terminated);
}
- isc_service_detach(status, &svc_handle);
+ if (isc_service_detach(status, &svc_handle))
+ {
+ isc_print_status(status);
+ return 1;
+ }
return 0;
}
catch (const Exception& e)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|