-=| Adam D. Barratt, 20.04.2013 16:57:45 +0100 |=- > Many apologies for not having got back to you about this at an > earlier point. I'm afraid it's a little too late to get the changes > in to the initial release (particularly as it would still need to go > via unstable first), although it may be worth looking at for > inclusion in a point release, assuming that would still be of > interest. Having this in .1 would be nice indeed. Thanks for coming back! > Looking through the list of changes, does #693193 cause an upgrade > issue from the 2.5.0 packages in squeeze? The description only > mentions 2.5.1, but I just wanted to check there wasn't any > potential impact on the older packages. Not really. The issue comes in certain situations (compound indices involving NULL values) when using the current wheezy package with a database created by firebird 2.5.1 (either a previous wheezy package from Feb-Oct 2011 or using upstream binary packages). If one used squeeze's firebird2.5 and upgraded to wheezy, there will be no problem since squeeze's server lacks the changes in 2.5.1 which aren't working well with current wheezy version. Attached is a source diff against the current wheezy package. Most of the changes are about the darwin port (build/*; not used in Debian) and related fcntl locking (src/jrd/isc_sync.cpp). firebird2.5 (2.5.2.26539.ds4-1) unstable; urgency=low * Official 2.5.2 release + CORE-3912: segfault in superclassic (Closes: #693192) + Restored the on-disk-structure compatibility with 2.5.1 index keys (Closes: #693193) + Fixed broken (working as no-op) sweep in SuperServer (Closes: #693195) + CORE-3902: Derived fields may not be optimized via an index (Closes: #693196) + CORE-3895: High memory usage when PSQL code SELECT's from stored procedure which modified some data (Closes: #693202) + CORE-3238: GEN_UUID returns a non-RFC-4122-compliant UUID (Closes: #693207) + CORE-3887: CHAR_TO_UUID and UUID_TO_CHAR works different in big endian architectures (Closes: #693209) + Enabled per-table runtime stats for sweeper + Changes not concerning Debian - CORE-3786: Hangs on MacOSX 10.7 (Lion) on DB create after reboot - CORE-3911: API entrypoints Bopen and BLOB_open are not visible on Darwin - CORE-3740: SELECT using IN list with >413 elements causes crash on Mac (stack overflow with default stack size) - CORE-3740: optimisation bug in GCC on Darwin * Update debian/copyright (two new files, no licensing changes) * Add NEWS.Debian about incompatible fix in char↔UUID conversion functions -- Damyan Ivanov <dmn@debian.org> Mon, 22 Apr 2013 17:23:19 +0300
diff --git a/ChangeLog b/ChangeLog index 7a2ccbd..47214ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,139 @@ + 2012-08-31 10:34 alexpeshkoff + M src/jrd/isc_sync.cpp +Better diagnostic (CORE-3786) + + 2012-08-31 10:27 alexpeshkoff + M src/remote/inet.cpp +Backported fix for CORE-3912: segfault in superclassic + + 2012-08-29 16:22 dimitr + M src/jrd/btr.cpp + M src/jrd/btr.h + M src/jrd/ods.h +Restored the ODS level compatibility with v2.5.1 index keys, while using the "old good" index key format in new indices. It allows to claim that CORE-3675 and CORE-3853 are fixed (after migration via backup/restore) but still operate almost correctly with keys created in v2.5.1. This is *much* better than silently returning wrong data if a v2.5.1 database is used with v2.5.2 without backup/restore. + + 2012-08-29 12:34 alexpeshkoff + M src/jrd/ibase.h + M src/jrd/utl.cpp + M src/jrd/utl_proto.h +Use better name from trunk for CORE-3911 + + 2012-08-29 11:35 alexpeshkoff + M src/jrd/ibase.h + M src/jrd/utl.cpp + M src/jrd/utl_proto.h +Fixed CORE-3911: API entrypoints Bopen and BLOB_open are not visible on Darwin + + 2012-08-29 11:30 alexpeshkoff + M src/jrd/ThreadStart.cpp +Fixed CORE-3740: SELECT using IN list with >413 elements causes crash on Mac + + 2012-08-28 18:00 dimitr + M src/jrd/tra.cpp +Misc. + + 2012-08-28 17:58 dimitr + M src/jrd/jrd.cpp + M src/jrd/tra.cpp + M src/jrd/tra_proto.h +Fixed the broken (working as no-op) sweep in SuperServer. +Minor cleanup and simplification. + + 2012-08-24 13:30 alexpeshkoff + M src/jrd/isc_sync.cpp +Better fix for CORE-3786: Firebird 2.5.1 Classic (32-bit) Hangs on MacOSX 10.7 (Lion) on DB create after reboot + + 2012-08-21 00:53 asfernandes + M src/dsql/gen.cpp +Backport fix for CORE-3902 - Derived fields may not be optimized via an index. + + 2012-08-15 15:22 dimitr + M src/jrd/nbak.h +Corrected the arguments. Luckily, their binary values are the same. + + 2012-08-14 10:37 alexpeshkoff + M src/jrd/isc.h + M src/jrd/isc_sync.cpp +Fixed CORE-3786: Firebird 2.5.1 Classic (32-bit) Hangs on MacOSX 10.7 (Lion) on DB create after reboot + + 2012-08-14 08:09 paulbeach + M builds/posix/darwin.defaults + A builds/posix/empty.darwin.vers + A builds/posix/firebird.darwin.vers +Allow build for 2.5.2 on MacOS + + 2012-08-13 16:49 dimitr + M src/common/classes/stack.h +Fixed the server crash in Stack::assign(). + + 2012-08-11 02:39 robocop + M src/jrd/trace/TraceJrdHelpers.h + M src/msgs/facilities2.sql + M src/msgs/history2.sql +Misc. + + 2012-08-08 14:38 paulbeach + M builds/posix/prefix.darwin_x86_64 +Fix CORE-3740 - optimisation bug in GCC + + 2012-07-29 00:21 robocop + M doc/sql.extensions/README.builtin_functions.txt +Misc. + + 2012-07-25 11:11 alexpeshkoff + M src/common/classes/semaphore.cpp + M src/common/fb_exception.cpp +Mac port + + 2012-07-23 09:20 hvlad + M src/jrd/exe.cpp + M src/jrd/tra.h +Fixed bug CORE-3895 : High memory usage when PSQL code SELECT's from stored procedure which modified some data + + 2012-07-16 10:43 alexpeshkoff + M src/utilities/fbsvcmgr.cpp +Removed debugging code + + 2012-07-12 06:33 robocop + M doc/README.services_extension +Misc. + + 2012-07-11 05:20 dimitr + M doc/WhatsNew +Updated the docs. + + 2012-07-11 01:38 asfernandes + M src/dsql/keywords.cpp + M src/dsql/parse.y +More changes related to CORE-3238 and CORE-3887. + + 2012-07-10 16:09 asfernandes + M doc/WhatsNew +Update. + + 2012-07-10 16:00 asfernandes + M doc/sql.extensions/README.builtin_functions.txt + M src/jrd/SysFunction.cpp + M src/jrd/os/guid.h + M src/jrd/trace/TraceService.cpp + M src/utilities/gstat/ppg.cpp + M src/utilities/nbackup.cpp +Rework on CORE-3238 - Makes GEN_UUID return a compliant RFC-4122 binary UUID. +Fixed CORE-3887 - CHAR_TO_UUID and UUID_TO_CHAR works different in big/little endian architectures - problem similar to CORE-2898. + + 2012-07-05 09:49 hvlad + M src/jrd/trace/TraceDSQLHelpers.h +Fixed bug CORE-3884 : Server crashes on preparing empty query when trace is enabled + + 2012-06-29 16:29 hvlad + M src/jrd/vio.cpp +Enabled per-table runtime stats for sweeper (necessary for CORE-3656). +I don't think it will have noticeable performance penalty on current HW. + + 2012-06-29 07:14 alexpeshkoff + M src/jrd/svc.cpp +Removed unused var - thanks to Adriano + 2012-06-28 10:53 hvlad M src/jrd/tra.cpp Improvement CORE-2668 : Write note into log when automatic sweep is started diff --git a/builds/posix/darwin.defaults b/builds/posix/darwin.defaults index 91f9607..0a73f78 100644 --- a/builds/posix/darwin.defaults +++ b/builds/posix/darwin.defaults @@ -29,6 +29,8 @@ LINK_FIREBIRD_CLIENT_SYMBOLS=$(LIB_LINK_MAPFILE)$(ROOT)/builds/posix/firebird.da LINK_FBINTL_SYMBOLS=$(LIB_LINK_MAPFILE)$(ROOT)/builds/posix/fbintl.darwin.vers LINK_IBUTIL_SYMBOLS=$(LIB_LINK_MAPFILE)$(ROOT)/builds/posix/ib_util.darwin.vers LINK_TRACE_SYMBOLS=$(LIB_LINK_MAPFILE)$(ROOT)/builds/posix/fbtrace.darwin.vers +LINK_EMPTY_SYMBOLS=$(LIB_LINK_MAPFILE)$(ROOT)/builds/posix/empty.darwin.vers +LINK_FIREBIRD_SYMBOLS=$(LIB_LINK_MAPFILE)$(ROOT)/builds/posix/firebird.darwin.vers LIB_LINK_RPATH:=-install_name /Library/Frameworks/Firebird.framework/Versions/A/Libraries/ LIB_EMBED_LINK_OPTIONS:=-install_name /Library/Frameworks/Firebird.framework/Versions/A/Firebird diff --git a/builds/posix/empty.darwin.vers b/builds/posix/empty.darwin.vers new file mode 100644 index 0000000..c160274 --- /dev/null +++ b/builds/posix/empty.darwin.vers @@ -0,0 +1,27 @@ +# +# Version script to hide private symbols from Firebird executables +# GNU and Solaris linkers should understand it +# +# +# The contents of this file are subject to the Interbase Public +# License Version 1.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy +# of the License at http://www.Inprise.com/IPL.html +# +# Software distributed under the License is distributed on an +# "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express +# or implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code was created by Inprise Corporation +# and its predecessors. Portions created by Inprise Corporation are +# Copyright (C) Inprise Corporation. +# +# Created from fbclient.def by Nickolay Samofatov +# +# All Rights Reserved. +# Contributor(s): ______________________________________. +# Alex Peshkov +# Paul Beach + + _main diff --git a/builds/posix/firebird.darwin.vers b/builds/posix/firebird.darwin.vers new file mode 100644 index 0000000..4b65667 --- /dev/null +++ b/builds/posix/firebird.darwin.vers @@ -0,0 +1,363 @@ +# +# Version script to hide private symbols from Firebird libraries +# GNU and Solaris linkers should understand it +# +# +# The contents of this file are subject to the Interbase Public +# License Version 1.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy +# of the License at http://www.Inprise.com/IPL.html +# +# Software distributed under the License is distributed on an +# "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express +# or implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code was created by Inprise Corporation +# and its predecessors. Portions created by Inprise Corporation are +# Copyright (C) Inprise Corporation. +# +# Created from fbclient.def by Nickolay Samofatov +# +# All Rights Reserved. +# Contributor(s): ______________________________________. + + +# private entrypoint for REMOTE server + _server_main +#------------------- +# PRIVATE INTERFACE +#------------------- + _gds__alloc + _gds__attach_database + _gds__blob_info + _gds__blob_size + _gds__cancel_blob + _gds__cancel_events + _gds__close + _gds__close_blob + _gds__commit_retaining + _gds__commit_transaction + _gds__compile_request + _gds__compile_request2 + _gds__create_blob + _gds__create_blob2 + _gds__create_database + _gds__database_cleanup + _gds__database_info + _gds__ddl + _gds__declare + _gds__decode + _gds__decode_date + _gds__describe + _gds__describe_bind + _gds__detach_database + _gds__disable_subsystem + _gds__dsql_finish + _gds__edit + _gds__enable_subsystem + _gds__encode + _gds__encode_date + _gds__event_block + _gds__event_counts + _gds__event_wait + _gds__execute + _gds__execute_immediate + _gds__fetch + _gds__free + _gds__ftof + _gds__get_prefix + _gds__get_segment + _gds__get_slice + _gds__interprete + _gds__log + _gds__log_status + _gds__map_blobs + _gds__msg_close + _gds__msg_format + _gds__msg_lookup + _gds__msg_open + _gds__msg_put + _gds__open + _gds__open_blob + _gds__open_blob2 + _gds__parse_bpb + _gds__prefix + _gds__prefix_lock + _gds__prefix_msg + _gds__prepare + _gds__prepare_transaction + _gds__prepare_transaction2 + _gds__print_blr + _gds__print_status + _gds__put_error + _gds__put_segment + _gds__put_slice + _gds__qtoq + _gds__que_events + _gds__receive + _gds__reconnect_transaction + _gds__register_cleanup + _gds__release_request + _gds__request_info + _gds__rollback_transaction + _gds__seek_blob + _gds__send + _gds__set_debug + _gds__sqlcode + _gds__start_and_send + _gds__start_multiple + _gds__start_request + _gds__start_transaction + _gds__temp_file + _gds__thread_enable + _gds__thread_enter + _gds__thread_exit + _gds__thread_start + _gds__to_sqlda + _gds__transaction_cleanup + _gds__transaction_info + _gds__unregister_cleanup + _gds__unwind_request + _gds__validate_lib_path + _gds__vax_integer + _gds__version + _gds__vtof + _gds__vtov + _gds__default_printer + + _gds__alloc_debug + + _gds_alloc_flag_unfreed + _gds_alloc_report + + _perf_format + _perf_get_info + _perf_report + +#---------------------------- +# PUBLIC INTERFACE, i.e. API +#---------------------------- + +# Array functions + + _isc_array_gen_sdl + _isc_array_get_slice + _isc_array_lookup_bounds + _isc_array_lookup_desc + _isc_array_put_slice + _isc_array_set_desc + _isc_get_slice + _isc_put_slice + +# BLOB functions + + _isc_blob_default_desc + _isc_blob_gen_bpb + _isc_blob_info + _isc_blob_lookup_desc + _isc_blob_set_desc + _isc_cancel_blob + _isc_close_blob + _isc_create_blob + _isc_create_blob2 + _isc_get_segment + _isc_open_blob + _isc_open_blob2 + _isc_put_segment + +# Database functions + + _isc_attach_database + _isc_create_database + _isc_database_info + _isc_detach_database + _isc_drop_database + _isc_expand_dpb + _isc_modify_dpb + _isc_version + _isc_get_client_major_version + _isc_get_client_minor_version + _isc_get_client_version + +# Conversion functions + + _isc_decode_date + _isc_decode_sql_date + _isc_decode_sql_time + _isc_decode_timestamp + _isc_encode_date + _isc_encode_sql_date + _isc_encode_sql_time + _isc_encode_timestamp + _isc_portable_integer + _isc_vax_integer + +# DSQL functions + + _isc_dsql_allocate_statement + _isc_dsql_alloc_statement2 + _isc_dsql_describe + _isc_dsql_describe_bind + _isc_dsql_execute + _isc_dsql_execute2 + _isc_dsql_execute_m + _isc_dsql_execute2_m + _isc_dsql_execute_immediate + _isc_dsql_exec_immed2 + _isc_dsql_execute_immediate_m + _isc_dsql_exec_immed2_m + _isc_dsql_exec_immed3_m + _isc_dsql_fetch + _isc_dsql_fetch_a + _isc_dsql_fetch_m + _isc_dsql_finish + _isc_dsql_free_statement + _isc_dsql_insert + _isc_dsql_insert_m + _isc_dsql_prepare + _isc_dsql_prepare_m + _isc_dsql_release + _isc_dsql_set_cursor_name + _isc_dsql_sql_info + +# ESQL functions + + _isc_embed_dsql_close + _isc_embed_dsql_declare + _isc_embed_dsql_describe + _isc_embed_dsql_describe_bind + _isc_embed_dsql_execute + _isc_embed_dsql_execute2 + _isc_embed_dsql_execute_immed + _isc_embed_dsql_exec_immed2 + _isc_embed_dsql_fetch + _isc_embed_dsql_fetch_a + _isc_embed_dsql_insert + _isc_embed_dsql_open + _isc_embed_dsql_open2 + _isc_embed_dsql_prepare + _isc_embed_dsql_release + +# Error-handling functions + + _isc_interprete + _fb_interpret + _isc_print_sqlerror + _isc_print_status + _isc_sqlcode + _isc_sql_interprete + +# Event functions + + _isc_cancel_events + _isc_event_block + _isc_event_counts + _isc_que_events + _isc_wait_for_event + +# Security functions + + #_isc_add_user + #_isc_delete_user + #_isc_modify_user + +# Services functions + + _isc_service_attach + _isc_service_detach + _isc_service_query + _isc_service_start + #functions called by utils + #SVC_putc + #SVC_finish + #SVC_output + #CMD_UTIL_put_svc_status + +# Transaction control functions + + _isc_commit_retaining + _isc_commit_transaction + _isc_prepare_transaction + _isc_prepare_transaction2 + _isc_rollback_retaining + _isc_rollback_transaction + _isc_start_multiple + _isc_start_transaction + _isc_transaction_info + +# Other functions + + _isc_compile_request + _isc_compile_request2 + _isc_ddl + _isc_prepare + _isc_receive + _isc_reconnect_transaction + _isc_release_request + _isc_request_info + _isc_seek_blob + _isc_send + _isc_start_and_send + _isc_start_request + _isc_transact_request + _isc_unwind_request + +# Other SQL functions + + _isc_close + _isc_declare + _isc_describe + _isc_describe_bind + _isc_execute + _isc_execute_immediate + _isc_fetch + _isc_fetch_a + _isc_open + +# Other BLOB functions + + _BLOB_close + _BLOB_display + _BLOB_dump + _BLOB_edit + _BLOB_get + _BLOB_load + _BLOB_open + _BLOB_put + _BLOB_text_dump + _BLOB_text_load + _Bopen + +# Other misc functions + + _isc_ftof + _isc_free + _isc_print_blr + _isc_qtoq + _isc_reset_fpe + _isc_set_debug + _isc_to_sqlda + _isc_vtof + _isc_vtov + +#----------------- +# OTHER FUNCTIONS +#----------------- + + _CVT_move + + _KEYWORD_stringIsAToken + _KEYWORD_getTokens + +#-------------------------------------- +#functions needed by Solaris utilities + _SCH_ast + +#commented it out with new style of thd //Konstantin +# +# THD_mutex_lock +# THD_mutex_unlock +# THD_mutex_destroy +# THD_mutex_init +#-------------------------------------- diff --git a/builds/posix/postfix.darwin b/builds/posix/postfix.darwin index 2b4cde8..9913024 100644 --- a/builds/posix/postfix.darwin +++ b/builds/posix/postfix.darwin @@ -36,6 +36,7 @@ darwin_setup_framework: ln -s ../../../../../../bin $(FB_FW)/Resources/English.lproj/var/bin ln -s ../../../../../../UDF $(FB_FW)/Resources/English.lproj/var/UDF ln -s ../../../../../../intl $(FB_FW)/Resources/English.lproj/var/intl + ln -s ../../../../../../plugins $(FB_FW)/Resources/English.lproj/var/plugins ln -s ../../../../../../security2.fdb \ $(FB_FW)/Resources/English.lproj/var/security2.fdb ln -s ../../../../../../help $(FB_FW)/Resources/English.lproj/var/help @@ -66,6 +67,9 @@ darwin_finish_cs_framework: cp ../builds/install/misc/fbintl.conf \ $(FB_FW)/Resources/English.lproj/var/intl/fbintl.conf chmod a+rx $(FB_FW)/Resources/English.lproj/var/intl/fbintl + mkdir -p $(FB_FW)/Resources/English.lproj/var/plugins + cp ../gen/firebird/plugins/libfbtrace.dylib \ + $(FB_FW)/Resources/English.lproj/var/plugins/libfbtrace.dylib cp -r ../gen/firebird/help $(FB_FW)/Resources/English.lproj/var/help cp ../gen/firebird/security2.fdb $(FB_FW)/Resources/English.lproj/var mkdir -p $(FB_FW)/Resources/doc @@ -132,6 +136,9 @@ darwin_finish_ss_framework: cp ../builds/install/misc/fbintl.conf \ $(FB_FW)/Resources/English.lproj/var/intl/fbintl.conf chmod a+rx $(FB_FW)/Resources/English.lproj/var/intl/fbintl + mkdir -p $(FB_FW)/Resources/English.lproj/var/plugins + cp ../gen/firebird/plugins/libfbtrace.dylib \ + $(FB_FW)/Resources/English.lproj/var/plugins/libfbtrace.dylib cp -r ../gen/firebird/help $(FB_FW)/Resources/English.lproj/var/help cp ../gen/firebird/security2.fdb $(FB_FW)/Resources/English.lproj/var mkdir -p $(FB_FW)/Resources/doc diff --git a/builds/posix/prefix.darwin_x86_64 b/builds/posix/prefix.darwin_x86_64 index 2ed16ae..d6004d2 100644 --- a/builds/posix/prefix.darwin_x86_64 +++ b/builds/posix/prefix.darwin_x86_64 @@ -27,7 +27,7 @@ export MACOSX_DEPLOYMENT_TARGET OS_ServerFiles=inet_server.cpp -PROD_FLAGS=-O3 -DDARWIN -pipe -p -MMD -fPIC -fno-common -mmacosx-version-min=10.6 +PROD_FLAGS=-O1 -DDARWIN -pipe -p -MMD -fPIC -fno-common -mmacosx-version-min=10.6 DEV_FLAGS=-ggdb -DDARWIN -pipe -p -MMD -fPIC -fno-common -Wall -mmacosx-version-min=10.6 CXXFLAGS:=$(CXXFLAGS) -fvisibility-inlines-hidden -fvisibility=hidden -fno-weak EMBED_UTIL_TARGETS=gstat gds_relay gsec fbguard nbackup fb_lock_print fbsvcmgr fbtracemgr diff --git a/debian/NEWS b/debian/NEWS new file mode 100644 index 0000000..88d7d14 --- /dev/null +++ b/debian/NEWS @@ -0,0 +1,16 @@ +firebird2.5 (2.5.2.26539.ds4-1) unstable; urgency=low + + Important for big-endian server installations: + + It has been discovered that before Firebird 2.5.2 (as packaged in debian + package version 2.5.2.26539.ds4-1), CHAR_TO_UUID and UUID_TO_CHAR + built-in functions work incorrectly on big-endian servers. On such machines, + bytes/characters are swapped and go in wrong positions when converting. The + bug is fixed in this release, but that means these functions now return + different values than before for the same input parameter. + + Additionally, the CHAR_TO_UUID2/UUID_TO_CHAR2 functions that were added as + fixed variants ot the buggy functions in the 2.5.2 development cycle are + dropped in this release. + + -- Damyan Ivanov <dmn@debian.org> Wed, 07 Nov 2012 17:52:10 +0200 diff --git a/debian/changelog b/debian/changelog index d46c066..401e9f2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,31 @@ +firebird2.5 (2.5.2.26539.ds4-1) unstable; urgency=low + + * Official 2.5.2 release + + CORE-3912: segfault in superclassic (Closes: #693192) + + Restored the on-disk-structure compatibility with 2.5.1 index keys + (Closes: #693193) + + Fixed broken (working as no-op) sweep in SuperServer (Closes: #693195) + + CORE-3902: Derived fields may not be optimized via an index + (Closes: #693196) + + CORE-3895: High memory usage when PSQL code SELECT's from stored + procedure which modified some data (Closes: #693202) + + CORE-3238: GEN_UUID returns a non-RFC-4122-compliant UUID + (Closes: #693207) + + CORE-3887: CHAR_TO_UUID and UUID_TO_CHAR works different in big endian + architectures (Closes: #693209) + + Enabled per-table runtime stats for sweeper + + Changes not concerning Debian + - CORE-3786: Hangs on MacOSX 10.7 (Lion) on DB create after reboot + - CORE-3911: API entrypoints Bopen and BLOB_open are not visible on Darwin + - CORE-3740: SELECT using IN list with >413 elements causes crash on Mac + (stack overflow with default stack size) + - CORE-3740: optimisation bug in GCC on Darwin + + * Update debian/copyright (two new files, no licensing changes) + * Add NEWS.Debian about incompatible fix in char↔UUID conversion functions + + -- Damyan Ivanov <dmn@debian.org> Mon, 22 Apr 2013 17:26:50 +0300 + firebird2.5 (2.5.2~svn+54698.ds4-3) unstable; urgency=high * Recover lost doc/libfbclient2 -> firebird2.5-common-doc symlink diff --git a/debian/copyright b/debian/copyright index 73b9eea..a5613c3 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1440,9 +1440,13 @@ src/jrd/tra.cpp src/lock/lock.cpp src/lock/lock.h Contributor(s): Nickolay Samofatov, Sean Leyne +builds/posix/firebird.darwin.vers builds/posix/firebird.hpux.vers builds/posix/firebird.vers - Created from fbclient.def by Nickolay Samofatov + Created from fbclient.def by Nickolay Samofatov +builds/posix/empty.darwin.vers + Created from fbclient.def by Nickolay Samofatov + Contributors: Alex Peshkov, Paul Beach builds/posix/postfix.darwin builds/posix/prefix.darwin_i386 builds/posix/prefix.darwin_powerpc diff --git a/doc/README.services_extension b/doc/README.services_extension index 8505df5..05631d3 100644 --- a/doc/README.services_extension +++ b/doc/README.services_extension @@ -158,7 +158,7 @@ See also README.trace_services 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. +internet, due to the great performance advantage. The simplest way to use this feature is fbsvcmgr. To backup database run approximately the following: @@ -186,7 +186,7 @@ server is ready to accept from client. (0 value means no more data is needed rig 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. +isc_info_svc_line tag in traditional 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(). diff --git a/doc/WhatsNew b/doc/WhatsNew index 5c04786..927c011 100644 --- a/doc/WhatsNew +++ b/doc/WhatsNew @@ -2,6 +2,27 @@ * v2.5.2 ************************** + * Bugfix CORE-3912 + Segmentation fault in SuperClassic + Contributor(s): + Alex Peshkov <peshkoff at mail.ru> + + * Bugfix CORE-3911 + API entrypoints Bopen and BLOB_open are not visible on MacOS + Contributor(s): + Alex Peshkov <peshkoff at mail.ru> + + * Bugfix CORE-3887 + CHAR_TO_UUID and UUID_TO_CHAR works different in big endian architectures + Contributor(s): + Adriano dos Santos Fernandes <adrianosf at uol.com.br> + + * Bugfix CORE-3884 + Server crashes on preparing empty query when trace is enabled + Contributor(s): + Dmitry Starodubov <dmitry.starodubov at red-soft.biz> + Vlad Khorsun <hvlad at users.sourceforge.net> + * Bugfix CORE-3875 GBAK does not check correctly parameters and backups random database with -B ":" Contributor(s): @@ -114,6 +135,11 @@ Nickolay Samofatov <skidder at users.sourceforge.net> Dmitry Yemanov <dimitr at firebirdsql.org> + * Bugfix CORE-3786 + Firebird 2.5.1 Classic (32-bit) Hangs on MacOSX 10.7 (Lion) on DB create after reboot + Contributor(s): + Alex Peshkov <peshkoff at mail.ru> + * Bugfix CORE-3778 Access violation at connection shutdown Contributor(s): @@ -149,6 +175,12 @@ Contributor(s): Alex Peshkov <peshkoff at mail.ru> + * Bugfix CORE-3740 + SELECT using IN list with 153 or more elements causes crash on MacOS + Contributor(s): + Paul Beach <pbeach at ibphoenix.com> + Alex Peshkov <peshkoff at mail.ru> + * Bugfix CORE-3736 WITH LOCK clause is allowed for users with read-only rights on some table, thus blocking others from updating this table @@ -322,8 +354,7 @@ Dmitry Yemanov <dimitr at firebirdsql.org> * Bugfix CORE-3238 - Makes GEN_UUID return a compliant RFC-4122 binary UUID and introduce - CHAR_TO_UUID2 and UUID_TO_CHAR2 to convert UUIDs from/to string also complying with the RFC + Makes GEN_UUID return a compliant RFC-4122 UUID Contributor(s): Adriano dos Santos Fernandes <adrianosf at uol.com.br> diff --git a/doc/sql.extensions/README.builtin_functions.txt b/doc/sql.extensions/README.builtin_functions.txt index 610fe7d..15c975d 100644 --- a/doc/sql.extensions/README.builtin_functions.txt +++ b/doc/sql.extensions/README.builtin_functions.txt @@ -246,36 +246,16 @@ Function: Format: CHAR_TO_UUID( <string> ) -Notes: - If you have not used this function before, its usage is discouraged. CHAR_TO_UUID2 supersedes it. +Important (for big-endian servers): + It has been discovered that before Firebird 2.5.2, CHAR_TO_UUID and UUID_TO_CHAR work + incorrectly in big-endian servers. In these machines, bytes/characters are swapped and go in + wrong positions when converting. This bug was fixed in 2.5.2 and 3.0, but that means these + functions now return different values (for the same input parameter) than before. Example: select char_to_uuid('93519227-8D50-4E47-81AA-8F6678C096A1') from rdb$database; -See also: GEN_UUID, CHAR_TO_UUID2, UUID_TO_CHAR and UUID_TO_CHAR2 - - -------------- -CHAR_TO_UUID2 -------------- - -Function: - Converts the CHAR(32) ASCII representation of an UUID - (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) to the CHAR(16) OCTETS - representation (optimized for storage). - -Format: - CHAR_TO_UUID2( <string> ) - -Notes: - This function supersedes CHAR_TO_UUID. The difference between them is that CHAR_TO_UUID does a - byte-by-byte conversion of the ASCII string to the OCTETS one, while CHAR_TO_UUID2 converts - a RFC-4122 compliant ASCII UUID to a compliant OCTETS string. - -Example: - select char_to_uuid2('93519227-8D50-4E47-81AA-8F6678C096A1') from rdb$database; - -See also: GEN_UUID, UUID_TO_CHAR2 +See also: GEN_UUID and UUID_TO_CHAR --- @@ -431,17 +411,17 @@ Function: Format: GEN_UUID() -Notes: - In Firebird 2.5.0 and 2.5.1, GEN_UUID was returning completely random strings. This is not - compliant with the RFC-4122 (UUID specification). - In Firebird 2.5.2 and 3.0 this was fixed. Now GEN_UUID returns a compliant UUID version 4 +Important: + Before Firebird 2.5.2, GEN_UUID was returning completely random strings. This is not compliant + with the RFC-4122 (UUID specification). + This was fixed in Firebird 2.5.2 and 3.0. Now GEN_UUID returns a compliant UUID version 4 string, where some bits are reserved and the others are random. The string format of a compliant UUID is XXXXXXXX-XXXX-4XXX-YXXX-XXXXXXXXXXXX, where 4 is fixed (version) and Y is 8, 9, A or B. Example: insert into records (id) value (gen_uuid()); -See also: CHAR_TO_UUID, UUID_TO_CHAR, CHAR_TO_UUID2, UUID_TO_CHAR2 +See also: CHAR_TO_UUID and UUID_TO_CHAR ---- @@ -869,33 +849,13 @@ Function: Format: UUID_TO_CHAR( <string> ) -Notes: - If you have not used this function before, its usage is discouraged. UUID_TO_CHAR2 supersedes it. +Important (for big-endian servers): + It has been discovered that before Firebird 2.5.2, CHAR_TO_UUID and UUID_TO_CHAR work + incorrectly in big-endian servers. In these machines, bytes/characters are swapped and go in + wrong positions when converting. This bug was fixed in 2.5.2 and 3.0, but that means these + functions now return different values (for the same input parameter) than before. Example: select uuid_to_char(gen_uuid()) from rdb$database; -See also: GEN_UUID, UUID_TO_CHAR2, CHAR_TO_UUID and CHAR_TO_UUID2 - - -------------- -UUID_TO_CHAR2 -------------- - -Function: - Converts a CHAR(16) OCTETS UUID (that's returned by GEN_UUID) to the - CHAR(32) ASCII representation (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). - -Format: - UUID_TO_CHAR2( <string> ) - -Notes: - This function supersedes UUID_TO_CHAR. The difference between them is that UUID_TO_CHAR does a - byte-by-byte conversion of the OCTETS string to the ASCII one, while UUID_TO_CHAR2 converts - a RFC-4122 compliant OCTETS UUID to a compliant ASCII string. Also, UUID_TO_CHAR returns - upper-cased string and UUID_TO_CHAR2 returns lower-cased string. - -Example: - select uuid_to_char2(gen_uuid()) from rdb$database; - -See also: GEN_UUID, CHAR_TO_UUID2 +See also: GEN_UUID and CHAR_TO_UUID diff --git a/src/common/classes/semaphore.cpp b/src/common/classes/semaphore.cpp index 844b1b4..760b956 100644 --- a/src/common/classes/semaphore.cpp +++ b/src/common/classes/semaphore.cpp @@ -281,9 +281,10 @@ static const char* semName = "/firebird_temp_sem"; } timespec timeout = getCurrentTime(); - nanoseconds += timeout.tv_nsec; - timeout.tv_sec += nanoseconds / 1000000000l; - timeout.tv_nsec = nanoseconds % 1000000000l; + timeout.tv_sec += milliseconds / 1000; + timeout.tv_nsec += (milliseconds % 1000) * 1000000; + timeout.tv_sec += (timeout.tv_nsec / 1000000000l); + timeout.tv_nsec %= 1000000000l; err = pthread_cond_timedwait(&cv, &mu, &timeout); mtxUnlock(); diff --git a/src/common/fb_exception.cpp b/src/common/fb_exception.cpp index a82f09e..19b4fb4 100644 --- a/src/common/fb_exception.cpp +++ b/src/common/fb_exception.cpp @@ -88,7 +88,7 @@ private: if (sigsetjmp(sigenv, 1) == 0) { Firebird::sync_signals_set(&sigenv); - if (pthread_kill(thread, 0) == ESRCH) + if (pthread_kill((pthread_t)thread, 0) == ESRCH) { // Thread does not exist any more thread = currTID; diff --git a/src/dsql/keywords.cpp b/src/dsql/keywords.cpp index b82cd7d..b5f1bf6 100644 --- a/src/dsql/keywords.cpp +++ b/src/dsql/keywords.cpp @@ -104,7 +104,6 @@ static const TOK tokens[] = {KW_CHAR, "CHAR", 1, false}, {CHAR_LENGTH, "CHAR_LENGTH", 2, false}, {CHAR_TO_UUID, "CHAR_TO_UUID", 2, false}, - {CHAR_TO_UUID2, "CHAR_TO_UUID2", 2, false}, {CHARACTER, "CHARACTER", 1, false}, {CHARACTER_LENGTH, "CHARACTER_LENGTH", 2, false}, {CHECK, "CHECK", 1, false}, @@ -384,7 +383,6 @@ static const TOK tokens[] = {USER, "USER", 1, false}, {USING, "USING", 2, false}, {UUID_TO_CHAR, "UUID_TO_CHAR", 2, false}, - {UUID_TO_CHAR2, "UUID_TO_CHAR2", 2, false}, {KW_VALUE, "VALUE", 1, false}, {VALUES, "VALUES", 1, false}, {VARCHAR, "VARCHAR", 1, false}, diff --git a/src/dsql/parse.y b/src/dsql/parse.y index e735256..4a115a4 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -543,7 +543,6 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string) %token AUTONOMOUS %token CHAR_TO_UUID -%token CHAR_TO_UUID2 %token FIRSTNAME %token GRANTED %token LASTNAME @@ -552,7 +551,6 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string) %token OS_NAME %token SIMILAR %token UUID_TO_CHAR -%token UUID_TO_CHAR2 %token DUMP @@ -4641,7 +4639,6 @@ system_function_std_syntax | BIN_XOR | CEIL | CHAR_TO_UUID - | CHAR_TO_UUID2 | COS | COSH | COT @@ -4674,7 +4671,6 @@ system_function_std_syntax | TANH | TRUNC | UUID_TO_CHAR - | UUID_TO_CHAR2 ; system_function_special_syntax @@ -5077,14 +5073,12 @@ non_reserved_word : | WEEK | AUTONOMOUS // added in FB 2.5 | CHAR_TO_UUID - | CHAR_TO_UUID2 | FIRSTNAME | MIDDLENAME | LASTNAME | MAPPING | OS_NAME | UUID_TO_CHAR - | UUID_TO_CHAR2 | GRANTED | CALLER // new execute statement | COMMON diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp index 18492f4..661e4f1 100644 --- a/src/jrd/SysFunction.cpp +++ b/src/jrd/SysFunction.cpp @@ -68,9 +68,7 @@ enum Function funLPad, funRPad, funLnat, - funLog10, - funUuidBroken, - funUuidRfc + funLog10 }; enum TrigonFunction @@ -1433,40 +1431,19 @@ dsc* evlCharToUuid(Jrd::thread_db* tdbb, const SysFunction* function, Jrd::jrd_n buffer[38] = '\0'; memcpy(buffer + 1, data, GUID_BODY_SIZE); - FB_GUID guid; - - switch ((Function)(IPTR) function->misc) - { - case funUuidBroken: - StringToGuid(&guid, buffer, false); - break; + USHORT bytes[16]; + sscanf(buffer, GUID_NEW_FORMAT, + &bytes[0], &bytes[1], &bytes[2], &bytes[3], + &bytes[4], &bytes[5], &bytes[6], &bytes[7], + &bytes[8], &bytes[9], &bytes[10], &bytes[11], + &bytes[12], &bytes[13], &bytes[14], &bytes[15]); - case funUuidRfc: - { - USHORT bytes[16]; - sscanf(buffer, GUID_NEW_FORMAT_LOWER, - &bytes[0], &bytes[1], &bytes[2], &bytes[3], - &bytes[4], &bytes[5], &bytes[6], &bytes[7], - &bytes[8], &bytes[9], &bytes[10], &bytes[11], - &bytes[12], &bytes[13], &bytes[14], &bytes[15]); - - guid.data1 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; - guid.data2 = (bytes[4] << 8) | bytes[5]; - guid.data3 = (bytes[6] << 8) | bytes[7]; - guid.data4[0] = bytes[8]; - guid.data4[1] = bytes[9]; - guid.data4[2] = bytes[10]; - guid.data4[3] = bytes[11]; - guid.data4[4] = bytes[12]; - guid.data4[5] = bytes[13]; - guid.data4[6] = bytes[14]; - guid.data4[7] = bytes[15]; - break; - } - } + UCHAR resultData[16]; + for (unsigned i = 0; i < 16; ++i) + resultData[i] = (UCHAR) bytes[i]; dsc result; - result.makeText(16, ttype_binary, reinterpret_cast<UCHAR*>(guid.data)); + result.makeText(16, ttype_binary, resultData); EVL_make_value(tdbb, &result, impure); return &impure->vlu_desc; @@ -1999,8 +1976,26 @@ dsc* evlGenUuid(Jrd::thread_db* tdbb, const SysFunction*, Jrd::jrd_nod* args, GenerateGuid(&guid); + UCHAR data[16]; + data[0] = (guid.data1 >> 24) & 0xFF; + data[1] = (guid.data1 >> 16) & 0xFF; + data[2] = (guid.data1 >> 8) & 0xFF; + data[3] = guid.data1 & 0xFF; + data[4] = (guid.data2 >> 8) & 0xFF; + data[5] = guid.data2 & 0xFF; + data[6] = (guid.data3 >> 8) & 0xFF; + data[7] = guid.data3 & 0xFF; + data[8] = guid.data4[0]; + data[9] = guid.data4[1]; + data[10] = guid.data4[2]; + data[11] = guid.data4[3]; + data[12] = guid.data4[4]; + data[13] = guid.data4[5]; + data[14] = guid.data4[6]; + data[15] = guid.data4[7]; + dsc result; - result.makeText(16, ttype_binary, reinterpret_cast<UCHAR*>(guid.data)); + result.makeText(16, ttype_binary, data); EVL_make_value(tdbb, &result, impure); return &impure->vlu_desc; @@ -3319,27 +3314,12 @@ dsc* evlUuidToChar(Jrd::thread_db* tdbb, const SysFunction* function, Jrd::jrd_n Arg::Str(function->name)); } - const FB_GUID* guid = reinterpret_cast<const FB_GUID*>(data); char buffer[GUID_BUFF_SIZE]; - - switch ((Function)(IPTR) function->misc) - { - case funUuidBroken: - GuidToString(buffer, guid, false); - break; - - case funUuidRfc: - sprintf(buffer, GUID_NEW_FORMAT_LOWER, - USHORT((guid->data1 >> 24) & 0xFF), USHORT((guid->data1 >> 16) & 0xFF), - USHORT((guid->data1 >> 8) & 0xFF), USHORT(guid->data1 & 0xFF), - USHORT((guid->data2 >> 8) & 0xFF), USHORT(guid->data2 & 0xFF), - USHORT((guid->data3 >> 8) & 0xFF), USHORT(guid->data3 & 0xFF), - USHORT(guid->data4[0]), USHORT(guid->data4[1]), - USHORT(guid->data4[2]), USHORT(guid->data4[3]), - USHORT(guid->data4[4]), USHORT(guid->data4[5]), - USHORT(guid->data4[6]), USHORT(guid->data4[7])); - break; - } + sprintf(buffer, GUID_NEW_FORMAT, + USHORT(data[0]), USHORT(data[1]), USHORT(data[2]), USHORT(data[3]), USHORT(data[4]), + USHORT(data[5]), USHORT(data[6]), USHORT(data[7]), USHORT(data[8]), USHORT(data[9]), + USHORT(data[10]), USHORT(data[11]), USHORT(data[12]), USHORT(data[13]), USHORT(data[14]), + USHORT(data[15])); dsc result; result.makeText(GUID_BODY_SIZE, ttype_ascii, reinterpret_cast<UCHAR*>(buffer) + 1); @@ -3374,8 +3354,7 @@ const SysFunction SysFunction::functions[] = {"BIN_XOR", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinXor}, {"CEIL", 1, 1, setParamsDouble, makeCeilFloor, evlCeil, NULL}, {"CEILING", 1, 1, setParamsDouble, makeCeilFloor, evlCeil, NULL}, - {"CHAR_TO_UUID", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, (void*) funUuidBroken}, - {"CHAR_TO_UUID2", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, (void*) funUuidRfc}, + {"CHAR_TO_UUID", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, NULL}, {"COS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCos}, {"COSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCosh}, {"COT", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCot}, @@ -3410,8 +3389,7 @@ const SysFunction SysFunction::functions[] = {"TAN", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfTan}, {"TANH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfTanh}, {"TRUNC", 1, 2, setParamsRoundTrunc, makeTrunc, evlTrunc, NULL}, - {"UUID_TO_CHAR", 1, 1, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, (void*) funUuidBroken}, - {"UUID_TO_CHAR2", 1, 1, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, (void*) funUuidRfc}, + {"UUID_TO_CHAR", 1, 1, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, NULL}, {"", 0, 0, NULL, NULL, NULL, NULL} }; diff --git a/src/jrd/ThreadStart.cpp b/src/jrd/ThreadStart.cpp index a782eb8..877496e 100644 --- a/src/jrd/ThreadStart.cpp +++ b/src/jrd/ThreadStart.cpp @@ -181,21 +181,23 @@ void ThreadStart::start(ThreadEntryPoint* routine, if (state) Firebird::system_call_failed::raise("pthread_attr_init", state); -#ifdef _AIX -// adjust stack size for AIX +#if defined(_AIX) || defined(DARWIN) +// adjust stack size // For AIX 32-bit compiled applications, the default stacksize is 96 KB, // see <pthread.h>. For 64-bit compiled applications, the default stacksize // is 192 KB. This is too small - see HP-UX note above +// For MaxOS default stack is 512 KB, which is also too small in 2012. + size_t stack_size; state = pthread_attr_getstacksize(&pattr, &stack_size); if (state) Firebird::system_call_failed::raise("pthread_attr_getstacksize"); - if (stack_size < 0x40000L) + if (stack_size < 0x400000L) { - state = pthread_attr_setstacksize(&pattr, 0x40000L); + state = pthread_attr_setstacksize(&pattr, 0x400000L); if (state) Firebird::system_call_failed::raise("pthread_attr_setstacksize", state); } diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index 6bd696e..2aa04fe 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -1283,15 +1283,24 @@ idx_e BTR_key(thread_db* tdbb, jrd_rel* relation, Record* record, index_desc* id (fuzzy ? INTL_KEY_PARTIAL : ((idx->idx_flags & idx_unique) ? INTL_KEY_UNIQUE : INTL_KEY_SORT))); - const UCHAR* q = temp.key_data; - for (USHORT l = temp.key_length; l; --l, --stuff_count) + if (temp.key_length) { - if (stuff_count == 0) + const UCHAR* q = temp.key_data; + for (USHORT l = temp.key_length; l; --l, --stuff_count) { - *p++ = idx->idx_count - n; - stuff_count = STUFF_COUNT; + if (stuff_count == 0) + { + *p++ = idx->idx_count - n; + stuff_count = STUFF_COUNT; + } + *p++ = *q++; } - *p++ = *q++; + } + else if (idx->idx_flags & idx_complete_segs) + { + fb_assert(stuff_count == 0); + *p++ = idx->idx_count - n; + stuff_count = STUFF_COUNT; } } key->key_length = (p - key->key_data); @@ -1662,15 +1671,24 @@ idx_e BTR_make_key(thread_db* tdbb, (idx->idx_flags & idx_descending), ((n == count - 1) ? (fuzzy ? INTL_KEY_PARTIAL : ((idx->idx_flags & idx_unique) ? INTL_KEY_UNIQUE : INTL_KEY_SORT)) : ((idx->idx_flags & idx_unique) ? INTL_KEY_UNIQUE : INTL_KEY_SORT))); - const UCHAR* q = temp.key_data; - for (USHORT l = temp.key_length; l; --l, --stuff_count) + if (temp.key_length) { - if (stuff_count == 0) + const UCHAR* q = temp.key_data; + for (USHORT l = temp.key_length; l; --l, --stuff_count) { - *p++ = idx->idx_count - n; - stuff_count = STUFF_COUNT; + if (stuff_count == 0) + { + *p++ = idx->idx_count - n; + stuff_count = STUFF_COUNT; + } + *p++ = *q++; } - *p++ = *q++; + } + else if (idx->idx_flags & idx_complete_segs) + { + fb_assert(stuff_count == 0); + *p++ = idx->idx_count - n; + stuff_count = STUFF_COUNT; } } @@ -1763,15 +1781,24 @@ void BTR_make_null_key(thread_db* tdbb, index_desc* idx, temporary_key* key) compress(tdbb, &null_desc, &temp, tail->idx_itype, true, (idx->idx_flags & idx_descending), false); - const UCHAR* q = temp.key_data; - for (USHORT l = temp.key_length; l; --l, --stuff_count) + if (temp.key_length) { - if (stuff_count == 0) + const UCHAR* q = temp.key_data; + for (USHORT l = temp.key_length; l; --l, --stuff_count) { - *p++ = idx->idx_count - n; - stuff_count = STUFF_COUNT; + if (stuff_count == 0) + { + *p++ = idx->idx_count - n; + stuff_count = STUFF_COUNT; + } + *p++ = *q++; } - *p++ = *q++; + } + else if (idx->idx_flags & idx_complete_segs) + { + fb_assert(stuff_count == 0); + *p++ = idx->idx_count - n; + stuff_count = STUFF_COUNT; } } key->key_length = (p - key->key_data); diff --git a/src/jrd/btr.h b/src/jrd/btr.h index d60c99d..f9a3079 100644 --- a/src/jrd/btr.h +++ b/src/jrd/btr.h @@ -122,6 +122,7 @@ const int idx_in_progress = 4; const int idx_foreign = 8; const int idx_primary = 16; const int idx_expressn = 32; +const int idx_complete_segs = 64; // these flags are for idx_runtime_flags diff --git a/src/jrd/build_no.h b/src/jrd/build_no.h index 76317a3..aeb891a 100644 --- a/src/jrd/build_no.h +++ b/src/jrd/build_no.h @@ -3,16 +3,16 @@ *** DO NOT EDIT *** TO CHANGE ANY INFORMATION IN HERE PLEASE EDIT src/misc/writeBuildNum.sh - FORMAL BUILD NUMBER:26508 + FORMAL BUILD NUMBER:26539 */ -#define PRODUCT_VER_STRING "2.5.2.26508" -#define FILE_VER_STRING "WI-V2.5.2.26508" -#define LICENSE_VER_STRING "WI-V2.5.2.26508" -#define FILE_VER_NUMBER 2, 5, 2, 26508 +#define PRODUCT_VER_STRING "2.5.2.26539" +#define FILE_VER_STRING "WI-V2.5.2.26539" +#define LICENSE_VER_STRING "WI-V2.5.2.26539" +#define FILE_VER_NUMBER 2, 5, 2, 26539 #define FB_MAJOR_VER "2" #define FB_MINOR_VER "5" #define FB_REV_NO "2" -#define FB_BUILD_NO "26508" +#define FB_BUILD_NO "26539" #define FB_BUILD_TYPE "V" #define FB_BUILD_SUFFIX "Firebird 2.5" diff --git a/src/jrd/ibase.h b/src/jrd/ibase.h index 6c8e758..d8cb9b0 100644 --- a/src/jrd/ibase.h +++ b/src/jrd/ibase.h @@ -154,7 +154,7 @@ typedef struct bstream short bstr_length; /* Length of buffer */ short bstr_cnt; /* Characters in buffer */ char bstr_mode; /* (mode) ? OUTPUT : INPUT */ -} BSTREAM; +} BSTREAM, *FB_BLOB_STREAM; /* Three ugly macros, one even using octal radix... sigh... */ #define getb(p) (--(p)->bstr_cnt >= 0 ? *(p)->bstr_ptr++ & 0377: BLOB_get (p)) diff --git a/src/jrd/isc.h b/src/jrd/isc.h index 9e894fb..cd82f2e 100644 --- a/src/jrd/isc.h +++ b/src/jrd/isc.h @@ -33,14 +33,20 @@ // Firebird platform-specific synchronization data structures -#if defined(DARWIN) || defined(FREEBSD) +#if defined(FREEBSD) #define USE_SYS5SEMAPHORE #endif +#if defined(DARWIN) +#define USE_FILELOCKS +#endif + +/* #if defined(USE_SYS5SEMAPHORE) && (defined(SUPERSERVER) || defined(FB_SUPER_UTIL)) #undef USE_SYS5SEMAPHORE #define USE_LOCAL_MUTEXES // this kills -c switch in fb_lock_print, but makes all the rest happy #endif + */ #ifdef LINUX // This hack fixes CORE-2896 - embedded connections fail on linux. @@ -48,6 +54,11 @@ #undef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL #endif //LINUX + +#ifdef USE_FILELOCKS +#define USE_SYS5SEMAPHORE +#endif + #ifdef UNIX #if defined(USE_POSIX_THREADS) diff --git a/src/jrd/isc_sync.cpp b/src/jrd/isc_sync.cpp index 52faad9..0eb814a 100644 --- a/src/jrd/isc_sync.cpp +++ b/src/jrd/isc_sync.cpp @@ -53,7 +53,6 @@ #include <sys/pstat.h> #endif -//#include "../common/classes/timestamp.h" #include "../jrd/common.h" #include "gen/iberror.h" #include "../jrd/isc.h" @@ -71,6 +70,7 @@ #include "../common/config/config.h" #include "../common/utils_proto.h" #include "../common/StatusArg.h" +#include "../common/classes/RefMutex.h" static int process_id; @@ -159,38 +159,252 @@ static bool event_blocked(const event_t* event, const SLONG value); #ifdef UNIX +#if defined(USE_FILELOCKS) || (!defined(HAVE_FLOCK)) +#define USE_FCNTL +#endif + static GlobalPtr<Mutex> openFdInit; + namespace { +#ifdef USE_FCNTL +class CountedRWLock +{ +public: + CountedRWLock() + : sharedAccessCounter(0) + { } + RWLock rwlock; + AtomicCounter cnt; + Mutex sharedAccessMutex; + int sharedAccessCounter; +}; + +class DevNode +{ +public: + DevNode() + : f_dev(0), f_ino(0) + { } + + DevNode(dev_t d, ino_t i) + : f_dev(d), f_ino(i) + { } + + DevNode(const DevNode& v) + : f_dev(v.f_dev), f_ino(v.f_ino) + { } + + dev_t f_dev; + ino_t f_ino; + + bool operator==(const DevNode& v) const + { + return f_dev == v.f_dev && f_ino == v.f_ino; + } + + bool operator>(const DevNode& v) const + { + return f_dev > v.f_dev ? true : + f_dev < v.f_dev ? false : + f_ino > v.f_ino; + } + + const DevNode& operator=(const DevNode& v) + { + f_dev = v.f_dev; + f_ino = v.f_ino; + return *this; + } +}; + +class CountedFd +{ +public: + CountedFd(int f) + : fd(f), useCount(0) + { } + + ~CountedFd() + { + fb_assert(useCount == 0); + } + + int fd; + int useCount; + +private: + CountedFd(const CountedFd&); + const CountedFd& operator=(const CountedFd&); +}; + + + typedef GenericMap<Pair<Left<string, CountedRWLock*> > > RWLocks; + GlobalPtr<RWLocks> rwlocks; + GlobalPtr<Mutex> rwlocksMutex; + + typedef GenericMap<Pair<NonPooled<DevNode, CountedFd*> > > FdNodes; + GlobalPtr<FdNodes> fdNodes; + GlobalPtr<Mutex> fdNodesMutex; + + DevNode getNode(const char* name) + { + struct stat statistics; + if (stat(name, &statistics) != 0) + { + if (errno == ENOENT) + { + //file not found + return DevNode(); + } + + system_call_failed::raise("stat"); + } + + return DevNode(statistics.st_dev, statistics.st_ino); + } + + DevNode getNode(int fd) + { + struct stat statistics; + if (fstat(fd, &statistics) != 0) + { + system_call_failed::raise("stat"); + } + + return DevNode(statistics.st_dev, statistics.st_ino); + } + + int openFile(const char* fileName) + { + MutexLockGuard g(fdNodesMutex); + + DevNode id(getNode(fileName)); + CountedFd** cFd = NULL; + if (id.f_ino) + { + cFd = fdNodes->get(id); + } + + if (!cFd) + { + int fd = os_utils::openCreateSharedFile(fileName, 0); + CountedFd* newFile = FB_NEW(*getDefaultMemoryPool()) CountedFd(fd); + cFd = fdNodes->put(getNode(fd)); + fb_assert(cFd); + *cFd = newFile; + } + + ++((*cFd)->useCount); + + return (*cFd)->fd; + } + + void closeFile(int fd) + { + MutexLockGuard g(fdNodesMutex); + + CountedFd** cFd = fdNodes->get(getNode(fd)); + fb_assert(cFd); + + if (--((*cFd)->useCount) == 0) + { + DevNode id(getNode(fd)); + close((*cFd)->fd); + delete *cFd; + fdNodes->remove(id); + } + } + + const char* NAME = "fcntl"; +#else + int openFile(const char* fileName) + { + return os_utils::openCreateSharedFile(fileName, 0); + } + + void closeFile(int fd) + { + close(fd); + } + + const char* NAME = "flock"; +#endif // USE_FCNTL + // File lock holder class FileLock { public: enum LockLevel {LCK_NONE, LCK_SHARED, LCK_EXCL}; enum DtorMode {CLOSED, OPENED, LOCKED}; + enum LockMode {FLM_EXCLUSIVE, FLM_TRY_EXCLUSIVE, FLM_SHARED, FLM_TRY_SHARED}; - FileLock(ISC_STATUS* pStatus, int pFd, DtorMode pMode = CLOSED) - : status(pStatus), level(LCK_NONE), fd(pFd), dtorMode(pMode) + FileLock(int pFd, DtorMode pMode = CLOSED, int s = 0) + : level(LCK_NONE), fd(pFd), dtorMode(pMode) +#ifdef USE_FCNTL + , start(s), rwcl(getRw()) +#endif { } ~FileLock() { - switch (dtorMode) + if (dtorMode != LOCKED) { - case LOCKED: - break; - case OPENED: unlock(); - break; - case CLOSED: + +#ifdef USE_FCNTL + MutexLockGuard g(rwlocksMutex); +#ifdef DEBUG_RWLOCKS + fprintf(stderr, "\n-- %p\n", rwcl); +#endif + if (--(rwcl->cnt) == 0) + { +#ifdef DEBUG_RWLOCKS + fprintf(stderr, "\nremove %p\n", rwcl); +#endif + rwlocks->remove(getLockId()); + delete rwcl; + } +#else /* USE_FCNTL */ unlock(); - close(fd); - break; +#endif /* USE_FCNTL */ + } + else + { +#ifdef DEBUG_RWLOCKS + fprintf(stderr, "\n~leave locked %p\n", rwcl); +#endif + } + + if (dtorMode == CLOSED) + { + closeFile(fd); } } - // unlocking can only put error into log file - we can't throw in dtors + void rwUnlock() + { +#ifdef USE_FCNTL + fb_assert(level != LCK_NONE); + + try + { + if (level == LCK_SHARED) + rwcl->rwlock.endRead(); + else + rwcl->rwlock.endWrite(); + } + catch(const Exception& ex) + { + iscLogException("rwlock end-operation error", ex); + } +#endif /* USE_FCNTL */ + + level = LCK_NONE; + } + + // unlocking can only put error into log file - we can't throw in dtors void unlock() { if (level == LCK_NONE) @@ -198,101 +412,257 @@ namespace { return; } -#ifdef HAVE_FLOCK - if (flock(fd, LOCK_UN)) -#else +#ifdef USE_FCNTL + // For shared lock we must take into an account reenterability + MutexEnsureUnlock guard(rwcl->sharedAccessMutex); + if (level == LCK_SHARED) + { + guard.enter(); + + fb_assert(rwcl->sharedAccessCounter > 0); + if (--(rwcl->sharedAccessCounter) > 0) + { + // counter is non-zero - we must keep file lock + rwUnlock(); + return; + } + } + struct flock lock; lock.l_type = F_UNLCK; - lock.l_whence = 0; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(fd, F_SETLK, &lock) == -1) -#endif + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = 1; + + if (fcntl(fd, F_SETLK, &lock) != 0) { +#else + if (flock(fd, LOCK_UN) != 0) + { +#endif ISC_STATUS_ARRAY local; error(local, NAME, errno); iscLogStatus("Unlock error", local); } - level = LCK_NONE; - } - // Call it to keep file locked & opened after dtor is called - void setDtorMode(DtorMode mode) throw() - { - dtorMode = mode; + rwUnlock(); } - // Call when using already locked file in ctor - void setLevel(LockLevel l) + // Main method to lock file + int doLock(const LockMode mode) { - level = l; - } + bool shared = true, wait = true; + switch(mode) + { + case FLM_TRY_EXCLUSIVE: + wait = false; + // fall through + case FLM_EXCLUSIVE: + shared = false; + break; + case FLM_TRY_SHARED: + wait = false; + // fall through + case FLM_SHARED: + break; + } - // All lock methods return true on success, false on error - bool exclusive() - { - return doLock(false, true); + const LockLevel newLevel = shared ? LCK_SHARED : LCK_EXCL; + if (newLevel == level) + { + return 0; + } + if (level != LCK_NONE) + { + unlock(); + } + +#ifdef USE_FCNTL + bool rc = true; + try + { + switch(mode) + { + case FLM_TRY_EXCLUSIVE: + rc = rwcl->rwlock.tryBeginWrite(); + break; + case FLM_EXCLUSIVE: + rwcl->rwlock.beginWrite(); + break; + case FLM_TRY_SHARED: + rc = rwcl->rwlock.tryBeginRead(); + break; + case FLM_SHARED: + rwcl->rwlock.beginRead(); + break; + } + } + catch(const system_call_failed& fail) + { + return fail.getErrorCode(); + } + if (!rc) + { + return -1; + } + + // For shared lock we must take into an account reenterability + MutexEnsureUnlock guard(rwcl->sharedAccessMutex); + if (shared) + { + if (wait) + { + guard.enter(); + } + else if (!guard.tryEnter()) + { + return -1; + } + + fb_assert(rwcl->sharedAccessCounter >= 0); + if (rwcl->sharedAccessCounter++ > 0) + { + // counter is non-zero - we already have file lock + level = LCK_SHARED; + return 0; + } + } + + struct flock lock; + lock.l_type = shared ? F_RDLCK : F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = 1; + if (fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock) == -1) + { + int rc = errno; + if ((!wait) && (rc == EACCES || rc == EAGAIN)) + { + rc = -1; + } + + try + { + if (newLevel == LCK_SHARED) + rwcl->rwlock.endRead(); + else + rwcl->rwlock.endWrite(); + } + catch(const Exception&) + { } + + return rc; +#else + if (flock(fd, (shared ? LOCK_SH : LOCK_EX) | (wait ? 0 : LOCK_NB))) + { + int rc = errno; + if ((!wait) && (rc == EWOULDBLOCK)) + { + rc = -1; + } + + return rc; +#endif + } + level = newLevel; + + return 0; } - bool tryExclusive() + // This file locker is using status vector to report errors + bool doLock(ISC_STATUS* const status, const LockMode mode) { - return doLock(false, false); + int rc = doLock(mode); + if (rc != 0) + { + if (rc > 0) + { + error(status, NAME, rc); + } + return false; + } + + return true; } - bool shared() + // Call it to keep file locked & opened after dtor is called + void setDtorMode(DtorMode mode) throw() { - return doLock(true, true); + dtorMode = mode; } - bool tryShared() + // Call when using already locked file in ctor + void setLevel(LockLevel l) { - return doLock(true, false); + level = l; +#ifdef USE_FCNTL + if (level != LCK_NONE) + { + // was not done in dtor + --(rwcl->cnt); +#ifdef DEBUG_RWLOCKS + fprintf(stderr, "\n-- %p\n", rwcl); +#endif + } +#endif } private: - ISC_STATUS* const status; LockLevel level; int fd; DtorMode dtorMode; - static const char* NAME; +#ifdef USE_FCNTL + int start; + CountedRWLock* rwcl; // Due to order of init in ctor rwlock must go after fd & start - private: - bool doLock(bool shared, bool wait) + string getLockId() { - const LockLevel newLevel = shared ? LCK_SHARED : LCK_EXCL; - if (newLevel == level) - { - return true; - } - if (level != LCK_NONE) + struct stat statistics; + fstat(fd, &statistics); + + const size_t len1 = sizeof(statistics.st_dev); + const size_t len2 = sizeof(statistics.st_ino); + const size_t len3 = sizeof(int); + + string rc(len1 + len2 + len3, ' '); + char* p = rc.begin(); + + memcpy(p, &statistics.st_dev, len1); + p += len1; + memcpy(p, &statistics.st_ino, len2); + p += len2; + memcpy(p, &start, len3); + + return rc; + } + + CountedRWLock* getRw() + { + string id = getLockId(); + CountedRWLock* rc = NULL; + + MutexLockGuard g(rwlocksMutex); + + CountedRWLock** got = rwlocks->get(id); + if (got) { - unlock(); + rc = *got; } -#ifdef HAVE_FLOCK - if (flock(fd, (shared ? LOCK_SH : LOCK_EX) | (wait ? 0 : LOCK_NB))) -#else //use FCNTL - struct flock lock; - lock.l_type = shared ? F_RDLCK : F_WRLCK; - lock.l_whence = 0; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock) == -1) -#endif + + if (!rc) { - error(status, NAME, errno); - return false; + rc = FB_NEW(*getDefaultMemoryPool()) CountedRWLock; + CountedRWLock** put = rwlocks->put(id); + fb_assert(put); + *put = rc; } - level = newLevel; - return true; - } - }; - const char* FileLock::NAME = -#ifdef HAVE_FLOCK - "flock"; -#else //use FCNTL - "fcntl"; + ++(rc->cnt); + + return rc; + } #endif + }; } #ifdef USE_SYS5SEMAPHORE @@ -312,7 +682,7 @@ namespace { class SemTable { public: - const static int N_FILES = 8; + const static int N_FILES = 128; const static int N_SETS = 256; #if defined(DEV_BUILD) const static int SEM_PER_SET = 4; // force multiple sets allocation @@ -507,18 +877,36 @@ namespace { class SharedFile { public: - SharedFile(const char* pName, UCHAR* address, int length) + SharedFile(const char* pName, int fd, UCHAR* address, int length) : fileNum(semTable->addFileByName(pName)), from(address), to(address + length) +#ifdef USE_FILELOCKS + , mutex(FB_NEW(*getDefaultMemoryPool()) FileLock(fd, FileLock::OPENED, 1)) +#endif + { } + + SharedFile() : fileNum(0), from(0), to(0) +#ifdef USE_FILELOCKS + , mutex(0) +#endif { } - SharedFile() : fileNum(0), from(0), to(0) { } + class StorageGuard : public MutexLockGuard + { + public: + StorageGuard() + : MutexLockGuard(guardMutex) + { } + + private: + static GlobalPtr<Mutex> guardMutex; + }; int getNum() const { return fileNum; } static SharedFile* locate(void* s) { const int n = getByAddress((UCHAR*) s); - return n >= 0 ? &sharedFiles[n] : 0; + return n >= 0 ? sharedFiles[n] : 0; } #ifdef DEB_EVNT @@ -545,78 +933,169 @@ namespace { AbsPtr rc; if (n >= 0) { - rc.offset = (IPTR)s - (IPTR)(sharedFiles[n].from); - rc.fn = sharedFiles[n].fileNum; + rc.offset = (IPTR)s - (IPTR)(sharedFiles[n]->from); + rc.fn = sharedFiles[n]->fileNum; } return rc; } #endif // DEB_EVNT - static void push(const SharedFile& sf) + static void push(SharedFile* sf) { - MutexLockGuard guard(mutex); - IPC_TRACE(("+add SF with %p %p\n", sf.from, sf.to)); + StorageGuard guard; + IPC_TRACE(("+add SF with %p %p\n", sf->from, sf->to)); sharedFiles.push(sf); } static void pop() { - MutexLockGuard guard(mutex); - SharedFile sf = sharedFiles.pop(); - IPC_TRACE(("-pop SF with %p %p\n", sf.from, sf.to)); + StorageGuard guard; + SharedFile* sf = sharedFiles.pop(); + sf->mutexDestroy(); + IPC_TRACE(("-pop SF with %p %p\n", sf->from, sf->to)); + delete sf; } static void remove(void* s) { - MutexLockGuard guard(mutex); + StorageGuard guard; int n = getByAddress((UCHAR*) s); if (n >= 0) { - IPC_TRACE(("-rem SF with %p %p\n", sharedFiles[n].from, sharedFiles[n].to)); + IPC_TRACE(("-rem SF with %p %p\n", sharedFiles[n]->from, sharedFiles[n]->to)); + sharedFiles[n]->mutexDestroy(); + delete sharedFiles[n]; sharedFiles.remove(n); } else { - IPC_TRACE(("-rem SF Failedp\n")); + IPC_TRACE(("-rem SF Failed\n")); } } static void remap(UCHAR* const from, UCHAR* to, int newLength, struct mtx** mtxPtr) { - MutexLockGuard guard(mutex); + StorageGuard guard; for (unsigned int n = 0; n < sharedFiles.getCount(); ++n) { - if (from == sharedFiles[n].from) + if (from == sharedFiles[n]->from) { if (mtxPtr) { UCHAR* m = (UCHAR*)(*mtxPtr); - if (m >= sharedFiles[n].from && m < sharedFiles[n].to) + if (m >= sharedFiles[n]->from && m < sharedFiles[n]->to) { - m = to + (m - sharedFiles[n].from); + m = to + (m - sharedFiles[n]->from); *mtxPtr = (struct mtx*)m; } } - sharedFiles[n].from = to; - sharedFiles[n].to = to + newLength; + sharedFiles[n]->from = to; + sharedFiles[n]->to = to + newLength; return; } } } - typedef Vector<SharedFile, SemTable::N_FILES> Storage; +#ifdef USE_FILELOCKS + + void mutexDestroy() + { + delete mutex; + mutex = 0; + } + + int mutexLock() + { + try + { + thrMutex.enter(); + } + catch(const system_call_failed& ex) + { + return ex.getErrorCode(); + } + + fb_assert(mutex); + int rc = mutex->doLock(FileLock::FLM_EXCLUSIVE); + if (rc) + { + try + { + thrMutex.leave(); + } + catch(const Exception& ex) + { } + } + return rc; + } + + int mutexTryLock() + { + try + { + if (!thrMutex.tryEnter()) + { + return EBUSY; + } + } + catch(const system_call_failed& ex) + { + return ex.getErrorCode(); + } + + fb_assert(mutex); + int rc = mutex->doLock(FileLock::FLM_TRY_EXCLUSIVE); + if (rc) + { + try + { + thrMutex.leave(); + } + catch(const Exception& ex) + { } + } + return rc; + } + + int mutexUnlock() + { + try + { + thrMutex.leave(); + } + catch(const system_call_failed& ex) + { + return ex.getErrorCode(); + } + + fb_assert(mutex); + mutex->unlock(); + return 0; + } + +#else // USE_FILELOCKS + + void mutexDestroy() + { } + +#endif // USE_FILELOCKS + + typedef Vector<SharedFile*, SemTable::N_FILES> Storage; private: int fileNum; const UCHAR* from; const UCHAR* to; +#ifdef USE_FILELOCKS + Mutex thrMutex; + FileLock* mutex; +#endif static Storage sharedFiles; - static GlobalPtr<Mutex> mutex; static int getByAddress(UCHAR* const s) { - MutexLockGuard guard(mutex); + StorageGuard guard; for (unsigned int n = 0; n < sharedFiles.getCount(); ++n) { - if (s >= sharedFiles[n].from && s < sharedFiles[n].to) + if (s >= sharedFiles[n]->from && s < sharedFiles[n]->to) { return n; } @@ -627,7 +1106,7 @@ namespace { }; SharedFile::Storage SharedFile::sharedFiles; - GlobalPtr<Mutex> SharedFile::mutex; + GlobalPtr<Mutex> SharedFile::StorageGuard::guardMutex; int idCache[SemTable::N_SETS]; GlobalPtr<Mutex> idCacheMutex; @@ -673,8 +1152,8 @@ namespace { ISC_STATUS_ARRAY status; // Lock init file. - FileLock initLock(status, fd_init, FileLock::OPENED); - if (!initLock.exclusive()) + FileLock initLock(fd_init, FileLock::OPENED); + if (!initLock.doLock(status, FileLock::FLM_EXCLUSIVE)) { iscLogStatus("initLock.exclusive() failed", status); return false; @@ -702,8 +1181,8 @@ namespace { ISC_STATUS_ARRAY status; // Lock init file. - FileLock initLock(status, fd_init, FileLock::OPENED); - if (!initLock.exclusive()) + FileLock initLock(fd_init, FileLock::OPENED); + if (!initLock.doLock(status, FileLock::FLM_EXCLUSIVE)) { iscLogStatus("freeSem5 failed to lock init file", status); return; @@ -1873,7 +2352,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, #else int #endif - fd_init = os_utils::openCreateSharedFile(init_filename, 0); + fd_init = openFile(init_filename); if (fd_init == -1) { error(status_vector, "open", errno); @@ -1881,11 +2360,11 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, } /* get an exclusive lock on the INIT file with blocking */ - FileLock initLock(status_vector, fd_init); + FileLock initLock(fd_init); #ifdef USE_SYS5SEMAPHORE initLock.setDtorMode(FileLock::OPENED); #endif - if (!initLock.exclusive()) + if (!initLock.doLock(status_vector, FileLock::FLM_EXCLUSIVE)) return NULL; // init file is locked - no races possible later in this function @@ -1895,7 +2374,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, { TEXT sem_filename[MAXPATHLEN]; gds__prefix_lock(sem_filename, SEM_FILE); - const int f = os_utils::openCreateSharedFile(sem_filename, 0); + const int f = openFile(sem_filename); if (f == -1) { error(status_vector, "open", errno); @@ -1914,18 +2393,18 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, } fb_assert(semTable); - FileLock semLock(status_vector, fdSem, FileLock::OPENED); + FileLock semLock(fdSem, FileLock::OPENED); - if (semLock.tryExclusive()) + if (semLock.doLock(status_vector, FileLock::FLM_TRY_EXCLUSIVE)) { semTable->init(); } - if (!semLock.shared()) + if (!semLock.doLock(status_vector, FileLock::FLM_SHARED)) return NULL; #endif /* open the file to be inited */ - const int fd = os_utils::openCreateSharedFile(expanded_filename, 0); + const int fd = openFile(expanded_filename); if (fd == -1) { error(status_vector, "open", errno); @@ -1933,7 +2412,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, } /* create lock in order to have file autoclosed on error */ - FileLock mainLock(status_vector, fd); + FileLock mainLock(fd); if (length == 0) { @@ -1973,7 +2452,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, class sfHolder { public: - explicit sfHolder(const SharedFile& sf) : pop(true) + explicit sfHolder(SharedFile* sf) : pop(true) { SharedFile::push(sf); } @@ -1993,14 +2472,15 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, private: bool pop; }; - sfHolder holder(SharedFile(expanded_filename, address, length)); + sfHolder holder(FB_NEW(*getDefaultMemoryPool()) + SharedFile(expanded_filename, fd, address, length)); #endif /* Try to get an exclusive lock on the lock file. This will fail if somebody else has the exclusive or shared lock */ - if (mainLock.tryExclusive()) + if (mainLock.doLock(status_vector, FileLock::FLM_TRY_EXCLUSIVE)) { if (!init_routine) { @@ -2014,7 +2494,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, (*init_routine) (init_arg, shmem_data, true); - if (!mainLock.tryShared()) + if (!mainLock.doLock(status_vector, FileLock::FLM_TRY_SHARED)) { munmap((char *) address, length); return NULL; @@ -2022,7 +2502,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, } else { - if (!mainLock.tryShared()) + if (!mainLock.doLock(status_vector, FileLock::FLM_TRY_SHARED)) { munmap((char *) address, length); return NULL; @@ -2034,6 +2514,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, /* keep opened the shared file_decriptor */ mainLock.setDtorMode(FileLock::LOCKED); + #ifdef USE_SYS5SEMAPHORE // keep shared lock before last shared memory region unmapped semLock.setDtorMode(FileLock::LOCKED); @@ -2595,7 +3076,7 @@ void ISC_unmap_mutex(mtx* mutex) #endif // HAVE_MAP_OBJECT } - + #ifdef USE_POSIX_THREADS @@ -2620,6 +3101,15 @@ int ISC_mutex_init(sh_mem* shmem_data, struct mtx* mutex, struct mtx** mapped) } mutex = *mapped; +#ifdef USE_FILELOCKS + + SharedFile* sf = SharedFile::locate(mutex); + if (!sf) + { + gds__log("SharedFile::locate(sem) failed"); + +#else // USE_FILELOCKS + if (!getSem5(mutex)) { return FB_FAILURE; @@ -2629,8 +3119,11 @@ int ISC_mutex_init(sh_mem* shmem_data, struct mtx* mutex, struct mtx** mapped) arg.val = 1; int state = semctl(mutex->getId(), mutex->semNum, SETVAL, arg); if (state == -1) - { + { iscLogStatus("ISC_mutex_init()", (Arg::Gds(isc_sys_request) << Arg::Str("semctl") << SYS_ERR(errno)).value()); + +#endif // USE_FILELOCKS + return FB_FAILURE; } @@ -2650,6 +3143,20 @@ void ISC_mutex_fini(struct mtx *mutex) * Destroy a mutex. * **************************************/ +#ifdef USE_FILELOCKS + + SharedFile* sf = SharedFile::locate(mutex); + if (!sf) + { + gds__log("SharedFile::locate(sem) failed"); + } + else + { + return sf->mutexDestroy(); + } + +#endif // USE_FILELOCKS + ISC_unmap_mutex(mutex); } @@ -2666,6 +3173,19 @@ int ISC_mutex_lock(struct mtx* mutex) * Seize a mutex. * **************************************/ +#ifdef USE_FILELOCKS + + SharedFile* sf = SharedFile::locate(mutex); + if (!sf) + { + gds__log("SharedFile::locate(sem) failed"); + return -1; + } + + return sf->mutexLock(); + +#else // USE_FILELOCKS + struct sembuf sop; sop.sem_num = mutex->semNum; sop.sem_op = -1; @@ -2678,9 +3198,12 @@ int ISC_mutex_lock(struct mtx* mutex) break; if (!SYSCALL_INTERRUPTED(errno)) return errno; - } + } return 0; + +#endif // USE_FILELOCKS + } @@ -2696,6 +3219,19 @@ int ISC_mutex_lock_cond(struct mtx* mutex) * Conditionally seize a mutex. * **************************************/ +#ifdef USE_FILELOCKS + + SharedFile* sf = SharedFile::locate(mutex); + if (!sf) + { + gds__log("SharedFile::locate(sem) failed"); + return -1; + } + + return sf->mutexTryLock(); + +#else // USE_FILELOCKS + struct sembuf sop; sop.sem_num = mutex->semNum; sop.sem_op = -1; @@ -2708,9 +3244,12 @@ int ISC_mutex_lock_cond(struct mtx* mutex) break; if (!SYSCALL_INTERRUPTED(errno)) return errno; - } + } return 0; + +#endif // USE_FILELOCKS + } @@ -2726,21 +3265,37 @@ int ISC_mutex_unlock(struct mtx* mutex) * Release a mutex. * **************************************/ +#ifdef USE_FILELOCKS + + SharedFile* sf = SharedFile::locate(mutex); + if (!sf) + { + gds__log("SharedFile::locate(sem) failed"); + return -1; + } + + sf->mutexUnlock(); + return 0; + +#else // USE_FILELOCKS + struct sembuf sop; sop.sem_num = mutex->semNum; sop.sem_op = 1; sop.sem_flg = SEM_UNDO; for (;;) - { + { int state = semop(mutex->getId(), &sop, 1); if (state != -1) break; if (!SYSCALL_INTERRUPTED(errno)) return errno; - } + } - return 0; + return 0; + +#endif // USE_FILELOCKS } #else // not USE_SYS5SEMAPHORE @@ -3577,8 +4132,8 @@ void ISC_unmap_file(ISC_STATUS* status_vector, sh_mem* shmem_data) **************************************/ #ifdef USE_SYS5SEMAPHORE // Lock init file. - FileLock initLock(status_vector, fd_init, FileLock::OPENED); - if (!initLock.exclusive()) + FileLock initLock(fd_init, FileLock::OPENED); + if (!initLock.doLock(status_vector, FileLock::FLM_EXCLUSIVE)) { iscLogStatus("ISC_unmap_file failed to lock init file", status_vector); } @@ -3586,9 +4141,9 @@ void ISC_unmap_file(ISC_STATUS* status_vector, sh_mem* shmem_data) { SharedFile* sf = SharedFile::locate(shmem_data->sh_mem_address); - FileLock lock(status_vector, shmem_data->sh_mem_handle); + FileLock lock(shmem_data->sh_mem_handle, FileLock::OPENED); lock.setLevel(FileLock::LCK_SHARED); - semTable->cleanup(sf->getNum(), lock.tryExclusive()); + semTable->cleanup(sf->getNum(), lock.doLock(status_vector, FileLock::FLM_TRY_EXCLUSIVE)); SharedFile::remove(shmem_data->sh_mem_address); } --sharedCount; @@ -3596,7 +4151,7 @@ void ISC_unmap_file(ISC_STATUS* status_vector, sh_mem* shmem_data) munmap((char *) shmem_data->sh_mem_address, shmem_data->sh_mem_length_mapped); - close(shmem_data->sh_mem_handle); + closeFile(shmem_data->sh_mem_handle); } #endif @@ -3633,7 +4188,7 @@ void ISC_unmap_file(ISC_STATUS* status_vector, sh_mem* shmem_data) TEXT expanded_filename[MAXPATHLEN]; gds__prefix_lock(expanded_filename, shmem_data->sh_mem_name); - + // Delete file only if it is not used by anyone else HANDLE hFile = CreateFile(expanded_filename, DELETE, diff --git a/src/jrd/ods.h b/src/jrd/ods.h index 0b144eb..c15d96f 100644 --- a/src/jrd/ods.h +++ b/src/jrd/ods.h @@ -358,6 +358,7 @@ const USHORT irt_in_progress = 4; const USHORT irt_foreign = 8; const USHORT irt_primary = 16; const USHORT irt_expression = 32; +const USHORT irt_complete_segs = 64; const int STUFF_COUNT = 4; const SLONG END_LEVEL = -1; diff --git a/src/jrd/os/guid.h b/src/jrd/os/guid.h index a4189fd..267414d 100644 --- a/src/jrd/os/guid.h +++ b/src/jrd/os/guid.h @@ -39,10 +39,8 @@ const int GUID_BODY_SIZE = 36; const char* const GUID_LEGACY_FORMAT = "{%04hX%04hX-%04hX-%04hX-%04hX-%04hX%04hX%04hX}"; -const char* const GUID_NEW_FORMAT_UPPER = +const char* const GUID_NEW_FORMAT = "{%02hX%02hX%02hX%02hX-%02hX%02hX-%02hX%02hX-%02hX%02hX-%02hX%02hX%02hX%02hX%02hX%02hX}"; -const char* const GUID_NEW_FORMAT_LOWER = - "{%02hx%02hx%02hx%02hx-%02hx%02hx-%02hx%02hx-%02hx%02hx-%02hx%02hx%02hx%02hx%02hx%02hx}"; struct FB_GUID { @@ -63,56 +61,21 @@ struct FB_GUID void GenerateRandomBytes(void* buffer, size_t size); void GenerateGuid(FB_GUID* guid); -// These functions receive buffers of at least GUID_BUFF_SIZE length +// These functions receive buffers of at least GUID_BUFF_SIZE length. +// Warning: they are BROKEN in little-endian and should not be used on new code. -inline void GuidToString(char* buffer, const FB_GUID* guid, bool legacy) +inline void GuidToString(char* buffer, const FB_GUID* guid) { - if (legacy) // nbackup guid - { - sprintf(buffer, GUID_LEGACY_FORMAT, - guid->data[0], guid->data[1], guid->data[2], guid->data[3], - guid->data[4], guid->data[5], guid->data[6], guid->data[7]); - } - else - { - sprintf(buffer, GUID_NEW_FORMAT_UPPER, - USHORT(guid->data[0] & 0xFF), USHORT(guid->data[0] >> 8), - USHORT(guid->data[1] & 0xFF), USHORT(guid->data[1] >> 8), - USHORT(guid->data[2] & 0xFF), USHORT(guid->data[2] >> 8), - USHORT(guid->data[3] & 0xFF), USHORT(guid->data[3] >> 8), - USHORT(guid->data[4] & 0xFF), USHORT(guid->data[4] >> 8), - USHORT(guid->data[5] & 0xFF), USHORT(guid->data[5] >> 8), - USHORT(guid->data[6] & 0xFF), USHORT(guid->data[6] >> 8), - USHORT(guid->data[7] & 0xFF), USHORT(guid->data[7] >> 8)); - } + sprintf(buffer, GUID_LEGACY_FORMAT, + guid->data[0], guid->data[1], guid->data[2], guid->data[3], + guid->data[4], guid->data[5], guid->data[6], guid->data[7]); } -inline void StringToGuid(FB_GUID* guid, const char* buffer, bool legacy) +inline void StringToGuid(FB_GUID* guid, const char* buffer) { - if (legacy) // nbackup guid - { - sscanf(buffer, GUID_LEGACY_FORMAT, - &guid->data[0], &guid->data[1], &guid->data[2], &guid->data[3], - &guid->data[4], &guid->data[5], &guid->data[6], &guid->data[7]); - } - else - { - USHORT bytes[16]; - sscanf(buffer, GUID_NEW_FORMAT_UPPER, - &bytes[0], &bytes[1], &bytes[2], &bytes[3], - &bytes[4], &bytes[5], &bytes[6], &bytes[7], - &bytes[8], &bytes[9], &bytes[10], &bytes[11], - &bytes[12], &bytes[13], &bytes[14], &bytes[15]); - - guid->data[0] = bytes[0] | (bytes[1] << 8); - guid->data[1] = bytes[2] | (bytes[3] << 8); - guid->data[2] = bytes[4] | (bytes[5] << 8); - guid->data[3] = bytes[6] | (bytes[7] << 8); - guid->data[4] = bytes[8] | (bytes[9] << 8); - guid->data[5] = bytes[10] | (bytes[11] << 8); - guid->data[6] = bytes[12] | (bytes[13] << 8); - guid->data[7] = bytes[14] | (bytes[15] << 8); - } + sscanf(buffer, GUID_LEGACY_FORMAT, + &guid->data[0], &guid->data[1], &guid->data[2], &guid->data[3], + &guid->data[4], &guid->data[5], &guid->data[6], &guid->data[7]); } #endif diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index 1bfda37..75b1246 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -1739,9 +1739,10 @@ bool TRA_sweep(thread_db* tdbb, jrd_tra* trans) if (dbb->dbb_flags & DBB_sweep_in_progress) return true; - if (tdbb->getAttachment()->att_flags & ATT_NO_CLEANUP) { + Attachment* attachment = tdbb->getAttachment(); + + if (attachment->att_flags & ATT_no_cleanup) return true; - } // fill out a lock block, zeroing it out first @@ -1785,14 +1786,12 @@ bool TRA_sweep(thread_db* tdbb, jrd_tra* trans) // during the course of the database sweep. Since it is used // below to advance the OIT we must save it before it changes. - if (!(transaction = trans)) transaction = TRA_start(tdbb, sizeof(sweep_tpb), sweep_tpb); SLONG transaction_oldest_active = transaction->tra_oldest_active; tdbb->setTransaction(transaction); - #ifdef GARBAGE_THREAD // The garbage collector runs asynchronously with respect to // our database sweep. This isn't good enough since we must @@ -1801,7 +1800,7 @@ bool TRA_sweep(thread_db* tdbb, jrd_tra* trans) // the "notify garbage collector" flag for the attachment and // synchronously perform the garbage collection ourselves. - transaction->tra_attachment->att_flags &= ~ATT_notify_gc; + attachment->att_flags &= ~ATT_notify_gc; #endif if (VIO_sweep(tdbb, transaction, &traceSweep)) @@ -1849,7 +1848,7 @@ bool TRA_sweep(thread_db* tdbb, jrd_tra* trans) CCH_RELEASE(tdbb, &window); - traceSweep.report(process_state_finished); + traceSweep.finish(); } if (!trans) @@ -3682,7 +3681,54 @@ TraceSweepEvent::~TraceSweepEvent() } -void TraceSweepEvent::report(ntrace_process_state_t state, jrd_rel* relation) +void TraceSweepEvent::beginSweepRelation(jrd_rel* relation) +{ + if (!m_need_trace) + return; + + if (relation && relation->rel_name.isEmpty()) + { + // don't accumulate per-relation stats for metadata query below + MET_lookup_relation_id(m_tdbb, relation->rel_id, false); + } + + m_relation_clock = fb_utils::query_performance_counter(); + m_request.req_stats.reset(); +} + + +void TraceSweepEvent::endSweepRelation(jrd_rel* relation) +{ + if (!m_need_trace) + return; + + // don't report empty relation + if (m_request.req_stats.getValue(RuntimeStatistics::RECORD_SEQ_READS) == 0 && + m_request.req_stats.getValue(RuntimeStatistics::RECORD_BACKOUTS) == 0 && + m_request.req_stats.getValue(RuntimeStatistics::RECORD_PURGES) == 0 && + m_request.req_stats.getValue(RuntimeStatistics::RECORD_EXPUNGES) == 0) + { + return; + } + + // we need to compare stats against zero base + m_request.req_base_stats.reset(); + + Database* dbb = m_tdbb->getDatabase(); + TraceRuntimeStats stats(dbb, &m_request.req_base_stats, &m_request.req_stats, + fb_utils::query_performance_counter() - m_relation_clock, + 0); + + m_sweep_info.setPerf(stats.getPerf()); + + Attachment* att = m_tdbb->getAttachment(); + TraceConnectionImpl conn(att); + TraceManager* trace_mgr = att->att_trace_manager; + trace_mgr->event_sweep(&conn, &m_sweep_info, process_state_progress); +} + + +void TraceSweepEvent::report(ntrace_process_state_t state) { Attachment* att = m_tdbb->getAttachment(); @@ -3706,26 +3752,13 @@ void TraceSweepEvent::report(ntrace_process_state_t state, jrd_rel* relation) TraceConnectionImpl conn(att); - if (relation && relation->rel_name.isEmpty()) - { - // don't accumulate per-relation stats for metadata query below - m_tdbb->setRequest(NULL); - MET_lookup_relation_id(m_tdbb, relation->rel_id, false); - m_tdbb->setRequest(&m_request); - } - // we need to compare stats against zero base m_request.req_base_stats.reset(); - TraceRuntimeStats stats(dbb, &m_request.req_base_stats, - state == process_state_progress ? &m_request.req_stats : &att->att_stats, - fb_utils::query_performance_counter() - (state == process_state_progress ? - m_relation_clock : m_start_clock), + TraceRuntimeStats stats(dbb, &m_request.req_base_stats, &att->att_stats, + fb_utils::query_performance_counter() - m_start_clock, 0); - m_request.req_stats.reset(); - m_relation_clock = fb_utils::query_performance_counter(); - m_sweep_info.setPerf(stats.getPerf()); trace_mgr->event_sweep(&conn, &m_sweep_info, state); diff --git a/src/jrd/trace/TraceDSQLHelpers.h b/src/jrd/trace/TraceDSQLHelpers.h index d957aed..66e8143 100644 --- a/src/jrd/trace/TraceDSQLHelpers.h +++ b/src/jrd/trace/TraceDSQLHelpers.h @@ -88,7 +88,7 @@ public: Firebird::string str(*getDefaultMemoryPool(), m_string, m_string_len); TraceFailedSQLStatement stmt(str); - TraceManager::event_dsql_prepare(m_attachment, m_request->req_transaction, + TraceManager::event_dsql_prepare(m_attachment, m_request ? m_request->req_transaction : NULL, &stmt, millis, result); } } diff --git a/src/jrd/trace/TraceJrdHelpers.h b/src/jrd/trace/TraceJrdHelpers.h index de32527..a563e1b 100644 --- a/src/jrd/trace/TraceJrdHelpers.h +++ b/src/jrd/trace/TraceJrdHelpers.h @@ -480,9 +480,17 @@ public: m_sweep_info.update(header); } - void report(ntrace_process_state_t state, jrd_rel* relation = 0); + void beginSweepRelation(jrd_rel* relation); + void endSweepRelation(jrd_rel* relation); + + void finish() + { + report(process_state_finished); + } private: + void report(ntrace_process_state_t state); + bool m_need_trace; thread_db* m_tdbb; TraceSweepImpl m_sweep_info; @@ -491,6 +499,7 @@ private: jrd_req m_request; }; + } // namespace Jrd #endif // JRD_TRACE_JRD_HELPERS_H diff --git a/src/jrd/trace/TraceService.cpp b/src/jrd/trace/TraceService.cpp index da202ee..432d894 100644 --- a/src/jrd/trace/TraceService.cpp +++ b/src/jrd/trace/TraceService.cpp @@ -107,7 +107,7 @@ void TraceSvcJrd::startSession(TraceSession& session, bool interactive) GenerateGuid(&guid); char* buff = session.ses_logfile.getBuffer(GUID_BUFF_SIZE); - GuidToString(buff, &guid, true); + GuidToString(buff, &guid); session.ses_logfile.insert(0, "fb_trace."); } diff --git a/src/jrd/utl.cpp b/src/jrd/utl.cpp index 516654b..fabc027 100644 --- a/src/jrd/utl.cpp +++ b/src/jrd/utl.cpp @@ -1261,7 +1261,7 @@ void API_ROUTINE isc_baddress_s(const SCHAR* object, uintptr_t* address) } -int API_ROUTINE BLOB_close(BSTREAM* bstream) +int API_ROUTINE BLOB_close(FB_BLOB_STREAM bstream) { /************************************** * @@ -1480,7 +1480,7 @@ int API_ROUTINE BLOB_edit(ISC_QUAD* blob_id, } -int API_ROUTINE BLOB_get(BSTREAM* bstream) +int API_ROUTINE BLOB_get(FB_BLOB_STREAM bstream) { /************************************** * @@ -1608,7 +1608,7 @@ int API_ROUTINE BLOB_load(ISC_QUAD* blob_id, } -BSTREAM* API_ROUTINE Bopen(ISC_QUAD* blob_id, +FB_BLOB_STREAM API_ROUTINE Bopen(ISC_QUAD* blob_id, FB_API_HANDLE database, FB_API_HANDLE transaction, const SCHAR* mode) @@ -1652,7 +1652,7 @@ BSTREAM* API_ROUTINE Bopen(ISC_QUAD* blob_id, return NULL; } - BSTREAM* bstream = BLOB_open(blob, NULL, 0); + FB_BLOB_STREAM bstream = BLOB_open(blob, NULL, 0); if (*mode == 'w' || *mode == 'W') { @@ -1671,7 +1671,7 @@ BSTREAM* API_ROUTINE Bopen(ISC_QUAD* blob_id, // CVC: This routine doesn't open a blob really! -BSTREAM* API_ROUTINE BLOB_open(FB_API_HANDLE blob, SCHAR* buffer, int length) +FB_BLOB_STREAM API_ROUTINE BLOB_open(FB_API_HANDLE blob, SCHAR* buffer, int length) { /************************************** * @@ -1686,7 +1686,7 @@ BSTREAM* API_ROUTINE BLOB_open(FB_API_HANDLE blob, SCHAR* buffer, int length) if (!blob) return NULL; - BSTREAM* bstream = (BSTREAM*) gds__alloc((SLONG) sizeof(BSTREAM)); + FB_BLOB_STREAM bstream = (FB_BLOB_STREAM) gds__alloc((SLONG) sizeof(BSTREAM)); // FREE: This structure is freed by BLOB_close if (!bstream) // NOMEM: return NULL; @@ -1726,7 +1726,7 @@ BSTREAM* API_ROUTINE BLOB_open(FB_API_HANDLE blob, SCHAR* buffer, int length) } -int API_ROUTINE BLOB_put(SCHAR x, BSTREAM* bstream) +int API_ROUTINE BLOB_put(SCHAR x, FB_BLOB_STREAM bstream) { /************************************** * diff --git a/src/jrd/utl_proto.h b/src/jrd/utl_proto.h index cd880c6..2a3a70c 100644 --- a/src/jrd/utl_proto.h +++ b/src/jrd/utl_proto.h @@ -26,6 +26,10 @@ #include "../include/fb_types.h" +#ifndef JRD_IBASE_H +typedef struct bstream* FB_BLOB_STREAM; +#endif + #ifdef __cplusplus extern "C" { #endif @@ -51,21 +55,21 @@ void API_ROUTINE isc_format_implementation(USHORT, USHORT, TEXT *, USHORT, USHORT, TEXT *); uintptr_t API_ROUTINE isc_baddress(SCHAR*); void API_ROUTINE isc_baddress_s(const SCHAR*, uintptr_t*); -int API_ROUTINE BLOB_close(struct bstream *); +int API_ROUTINE BLOB_close(FB_BLOB_STREAM); int API_ROUTINE blob__display(SLONG*, FB_API_HANDLE*, FB_API_HANDLE*, const TEXT*, const SSHORT*); int API_ROUTINE BLOB_display(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const TEXT*); int API_ROUTINE blob__dump(SLONG*, FB_API_HANDLE*, FB_API_HANDLE*, const TEXT*, const SSHORT*); int API_ROUTINE BLOB_dump(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const SCHAR*); int API_ROUTINE blob__edit(SLONG*, FB_API_HANDLE*, FB_API_HANDLE*, const TEXT*, const SSHORT*); int API_ROUTINE BLOB_edit(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const SCHAR*); -int API_ROUTINE BLOB_get(struct bstream*); +int API_ROUTINE BLOB_get(FB_BLOB_STREAM); int API_ROUTINE blob__load(SLONG*, FB_API_HANDLE*, FB_API_HANDLE*, const TEXT*, const SSHORT*); int API_ROUTINE BLOB_load(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const TEXT*); int API_ROUTINE BLOB_text_dump(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const SCHAR*); int API_ROUTINE BLOB_text_load(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const TEXT*); -struct bstream* API_ROUTINE Bopen(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const SCHAR*); -struct bstream* API_ROUTINE BLOB_open(FB_API_HANDLE, SCHAR*, int); -int API_ROUTINE BLOB_put(SCHAR, struct bstream*); +FB_BLOB_STREAM API_ROUTINE Bopen(ISC_QUAD*, FB_API_HANDLE, FB_API_HANDLE, const SCHAR*); +FB_BLOB_STREAM API_ROUTINE BLOB_open(FB_API_HANDLE, SCHAR*, int); +int API_ROUTINE BLOB_put(SCHAR, FB_BLOB_STREAM); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index b09fc75..cdfe9b5 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -2926,7 +2926,6 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee for (size_t i = 1; (vector = dbb->dbb_relations) && i < vector->count(); i++) { - bool haveRecs = false; if ((relation = (*vector)[i]) && !(relation->rel_flags & (REL_deleted | REL_deleting)) && relation->getPages(tdbb)->rel_pages) { @@ -2934,6 +2933,9 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee rpb.rpb_number.setValue(BOF_NUMBER); rpb.rpb_org_scans = relation->rel_scan_count++; ++relation->rel_sweep_count; + + traceSweep->beginSweepRelation(relation); + #ifdef GARBAGE_THREAD if (relation->rel_garbage) { relation->rel_garbage->clear(); @@ -2955,12 +2957,9 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee #ifdef SUPERSERVER transaction->tra_oldest_active = dbb->dbb_oldest_snapshot; #endif - haveRecs = true; } - if (haveRecs) { - traceSweep->report(process_state_progress, relation); - } + traceSweep->endSweepRelation(relation); --relation->rel_sweep_count; --relation->rel_scan_count; diff --git a/src/misc/writeBuildNum.sh b/src/misc/writeBuildNum.sh index be9ff0b..e84ca36 100755 --- a/src/misc/writeBuildNum.sh +++ b/src/misc/writeBuildNum.sh @@ -9,7 +9,7 @@ BuildType=V MajorVer=2 MinorVer=5 RevNo=2 -BuildNum=26508 +BuildNum=26539 if [ "$SPECIAL_BUILD_SUFFIX" = "" ]; then # Normal builds diff --git a/src/remote/inet.cpp b/src/remote/inet.cpp index f662ca4..bfe7bc7 100644 --- a/src/remote/inet.cpp +++ b/src/remote/inet.cpp @@ -265,12 +265,22 @@ public: Select() : slct_time(0), slct_count(0), slct_poll(*getDefaultMemoryPool()) { } + + Select(Firebird::MemoryPool& pool) + : slct_time(0), slct_count(0), slct_poll(pool) + { } #else Select() : slct_time(0), slct_count(0), slct_width(0) { memset(&slct_fdset, 0, sizeof slct_fdset); } + + Select(Firebird::MemoryPool& /*pool*/) + : slct_time(0), slct_count(0), slct_width(0) + { + memset(&slct_fdset, 0, sizeof slct_fdset); + } #endif enum HandleState {SEL_BAD, SEL_DISCONNECTED, SEL_NO_DATA, SEL_READY}; @@ -532,7 +542,7 @@ SLONG INET_remote_buffer; static Firebird::GlobalPtr<Firebird::Mutex> init_mutex; static volatile bool INET_initialized = false; static volatile bool INET_shutting_down = false; -static Select INET_select; +static Firebird::GlobalPtr<Select> INET_select; static int INET_max_clients; static rem_port* inet_async_receive = NULL; diff --git a/src/utilities/gstat/ppg.cpp b/src/utilities/gstat/ppg.cpp index e3cfb18..2a34c33 100644 --- a/src/utilities/gstat/ppg.cpp +++ b/src/utilities/gstat/ppg.cpp @@ -251,7 +251,7 @@ void PPG_print_header(const header_page* header, SLONG page, case HDR_backup_guid: { char buff[GUID_BUFF_SIZE]; - GuidToString(buff, reinterpret_cast<const FB_GUID*>(p + 2), true); + GuidToString(buff, reinterpret_cast<const FB_GUID*>(p + 2)); uSvc->printf(false, "\tDatabase backup GUID:\t%s\n", buff); break; } diff --git a/src/utilities/nbackup.cpp b/src/utilities/nbackup.cpp index ff0f4f7..7deb474 100644 --- a/src/utilities/nbackup.cpp +++ b/src/utilities/nbackup.cpp @@ -890,7 +890,7 @@ void NBackup::backup_database(int level, const PathName& fname) bh.version = 1; bh.level = level; bh.backup_guid = backup_guid; - StringToGuid(&bh.prev_guid, prev_guid, true); + StringToGuid(&bh.prev_guid, prev_guid); bh.page_size = header->hdr_page_size; bh.backup_scn = backup_scn; bh.prev_scn = prev_scn; @@ -990,7 +990,7 @@ void NBackup::backup_database(int level, const PathName& fname) in_sqlda->sqlvar[0].sqldata = (char*)&level; in_sqlda->sqlvar[0].sqlind = &null_flag; char temp[GUID_BUFF_SIZE]; - GuidToString(temp, &backup_guid, true); + GuidToString(temp, &backup_guid); in_sqlda->sqlvar[1].sqldata = temp; in_sqlda->sqlvar[1].sqlind = &null_flag; in_sqlda->sqlvar[2].sqldata = (char*)&backup_scn; diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index 7b8b278..3c50c82 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -2004,6 +2004,9 @@ void TracePluginImpl::log_event_error(TraceBaseConnection* connection, TraceStat void TracePluginImpl::log_event_sweep(TraceDatabaseConnection* connection, TraceSweepInfo* sweep, ntrace_process_state_t sweep_state) { + if (!config.log_sweep) + return; + if (sweep_state == process_state_started || sweep_state == process_state_finished) {
Attachment:
signature.asc
Description: Digital signature