[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#693216: preapproval of firebird2.5/2.5.2.26539.ds4-1



-=| 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


Reply to: