Commit graph

40 commits

Author SHA1 Message Date
marko
1c0cf56c45 branches/zip: row_update_prebuilt_trx(): Correct bogus comment. 2009-05-19 08:41:32 +00:00
marko
ab67f4eb4a branches/zip: Refuse to use newly created indexes that may lack
history.  This addresses Mantis issue #116.

dict_index_t: Enable the storage of trx_id.

row_prebuilt_t: Make many fields bit-fields to reduce the memory
footprint. Add index_usable.

ha_innobase::change_active_index(): Check if the index is usable and
set prebuilt->index_usable accordingly. Unfortunately, the return
status of this function is ignored by MySQL, and the actual refusal to
use the index must be made in row_search_for_mysql().

row_search_for_mysql(): Return DB_MISSING_HISTORY if
!prebuilt->index_usable.

convert_error_code_to_mysql(): Map DB_MISSING_HISTORY to
HA_ERR_TABLE_DEF_CHANGED.

innodb-index.test: Add a test case where access to a newly created
secondary index must be blocked for old transactions.

rb://100 approved by Heikki Tuuri
2009-04-02 12:23:12 +00:00
marko
349090707c branches/zip: Remove references to UNIV_HOTBACKUP from files that are
not used when building InnoDB Hot Backup.  Declare
innobase_invalidate_query_cache() in ha_prototypes.h.
2009-03-24 12:02:29 +00:00
marko
48070b5332 branches/zip: Merge revisions 4359:4400 from branches/5.1:
------------------------------------------------------------------------
  r4399 | marko | 2009-03-12 09:38:05 +0200 (Thu, 12 Mar 2009) | 2 lines

  branches/5.1: row_sel_get_clust_rec_for_mysql(): Store the cursor position
  also for unlock_row().  (Bug #39320)
  ------------------------------------------------------------------------
  r4400 | marko | 2009-03-12 10:06:44 +0200 (Thu, 12 Mar 2009) | 5 lines

  branches/5.1: Fix a bug in multi-table semi-consistent reads.
  Remember the acquired record locks per table handle (row_prebuilt_t)
  rather than per transaction (trx_t), so that unlock_row should successfully
  unlock all non-matching rows in multi-table operations.
  This deficiency was found while investigating Bug #39320.
  ------------------------------------------------------------------------

These were submitted as rb://94 and rb://96 and approved by Heikki Tuuri.
2009-03-12 08:26:40 +00:00
vasil
3755fe658c branches/zip:
* Remove old Innobase copyright lines from C source files
* Add a reference to the GPLv2 license as recommended by the lawyers
at Oracle Legal

[Step 16/28]
2009-02-17 09:33:38 +00:00
marko
d1b5613fa0 branches/zip: Merge revisions 3479:3598 from branches/5.1:
------------------------------------------------------------------------
  r3588 | inaam | 2008-12-18 14:26:54 +0200 (Thu, 18 Dec 2008) | 8 lines

  branches/5.1

  It is a bug in unused code. If we don't calculate the hash value when
  calculating the mutex number then two pages which map to same hash
  value can get two different mutex numbers.

  Approved by: Marko
  ------------------------------------------------------------------------
  r3590 | marko | 2008-12-18 15:33:36 +0200 (Thu, 18 Dec 2008) | 11 lines

  branches/5.1: When converting a record to MySQL format, copy the default
  column values for columns that are SQL NULL.  This addresses failures in
  row-based replication (Bug #39648).

  row_prebuilt_t: Add default_rec, for the default values of the columns in
  MySQL format.

  row_sel_store_mysql_rec(): Use prebuilt->default_rec instead of
  padding columns.

  rb://64 approved by Heikki Tuuri
  ------------------------------------------------------------------------
  r3598 | marko | 2008-12-22 15:28:03 +0200 (Mon, 22 Dec 2008) | 6 lines

  branches/5.1: ibuf_delete_rec(): When the record cannot be found and
  the tablespace has been dropped, commit the mini-transaction, so that
  InnoDB will not hold the insert buffer tree latch in exclusive mode,
  causing a potential deadlock.  This bug was introduced in the fix of
  Bug #27276 in r2924.
  ------------------------------------------------------------------------
2008-12-22 13:41:47 +00:00
marko
5697b755e6 branches/zip: Pass the caller's file name and line number to
row_mysql_lock_data_dictionary(), row_mysql_freeze_data_dictionary(),
to better track down locking issues that involve dict_operation_lock.
2008-12-22 10:27:16 +00:00
sunny
7fed1c703e branches/zip:
1. We add a vector of locks to trx_t. This array contains the autoinc
  locks granted to a transaction. There is one per table.

  2. We enforce releasing of these locks in the reverse order from the
  one in which they are acquired. The assumption is that since the
  AUTOINC locks are statement level locks. Nested statements introduced
  by triggers are stacked it should hold.

There was some cleanup done to the vector code too by adding const and
some new functions. Rename dict_table_t::auto_inc_lock to autoinc_lock.

Fix Bug#26316 Triggers create duplicate entries on auto-increment columns
rb://22
2008-10-31 07:40:29 +00:00
sunny
f9c42d81e7 branches/zip:
Merge revisions 2837:2852 from branches/5.1:

  ------------------------------------------------------------------------
  r2849 | sunny | 2008-10-22 12:01:18 +0300 (Wed, 22 Oct 2008) | 8 lines
  Changed paths:
     M /branches/5.1/handler/ha_innodb.cc
     M /branches/5.1/include/row0mysql.h
     M /branches/5.1/row/row0mysql.c
  
  branches/5.1: Return the actual error code encountered when allocating
  a new autoinc value. The change in behavior (bug) was introduced in 5.1.22
  when we introduced the new AUTOINC locking model.
  
  rb://31
  
  Bug#40224 New AUTOINC changes mask reporting of deadlock/timeout errors
  
  ------------------------------------------------------------------------
  r2852 | sunny | 2008-10-23 01:42:24 +0300 (Thu, 23 Oct 2008) | 9 lines
  Changed paths:
     M /branches/5.1/handler/ha_innodb.cc
     M /branches/5.1/handler/ha_innodb.h
  
  branches/5.1: Backport r2724 from branches/zip
  
  Check column value against the col max value before updating the table's
  global autoinc counter value. This is part of simplifying the AUTOINC
  sub-system. We extract the type info from MySQL data structures at runtime.
  
  This fixes Bug#37788 InnoDB Plugin: AUTO_INCREMENT wrong for compressed tables
  
  
  ------------------------------------------------------------------------
2008-10-23 05:29:46 +00:00
marko
344481d597 branches/zip: row_create_table_for_mysql(), row_create_index_for_mysql():
Note that the dictionary object will be freed.
2008-10-15 06:00:06 +00:00
marko
a9a21fb983 branches/zip: Do not release the data dictionary latch while holding locks
to the data dictionary records.  This should fix Issue #83.

row_drop_table_for_mysql_no_commit(): Rename back to
row_drop_table_for_mysql().  Commit the transaction if the data
dictionary was not locked when the function was called.  Otherwise,
neither commit the transaction nor unlock the data dictionary.

row_merge_drop_table(): Let row_drop_table_for_mysql() take care of
locking the data dictionary.

dict_create_or_check_foreign_constraint_tables(),
trx_rollback_active(), row_create_table_for_mysql(),
row_create_index_for_mysql(), row_table_add_foreign_constraints():
Explicitly commit the transaction, because row_drop_table_for_mysql()
would no longer commit it, given that the data dictionary will be
locked during the calls.

Approved by Sunny (over IM). rb://23
2008-10-08 08:54:16 +00:00
sunny
cb0cacc2d8 branches/zip: Merge revisions 2702:2722 from branches/5.1:
------------------------------------------------------------------------
  r2702 | sunny | 2008-09-30 11:41:56 +0300 (Tue, 30 Sep 2008) | 13 lines
  Changed paths:
     M /branches/5.1/handler/ha_innodb.cc
  
  branches/5.1: Since handler::get_auto_increment() doesn't allow us
  to return the cause of failure we have to inform MySQL using the
  sql_print_warning() function to return the cause for autoinc failure.
  Previously we simply printed the error code, this patch prints the
  text string representing the following two error codes:
  
  DB_LOCK_WAIT_TIMEOUT
  DB_DEADLOCK.
  
  Bug#35498 Cannot get table test/table1 auto-inccounter value in ::info
  
  Approved by Marko.
  
  ------------------------------------------------------------------------
  r2709 | vasil | 2008-10-01 10:13:13 +0300 (Wed, 01 Oct 2008) | 10 lines
  Changed paths:
     M /branches/5.1/include/lock0lock.h
     M /branches/5.1/lock/lock0lock.c
     A /branches/5.1/mysql-test/innodb_bug38231.result
     A /branches/5.1/mysql-test/innodb_bug38231.test
     M /branches/5.1/row/row0mysql.c
  
  branches/5.1:
  
  Fix Bug#38231 Innodb crash in lock_reset_all_on_table() on TRUNCATE + LOCK / UNLOCK
  
  In TRUNCATE TABLE and discard tablespace: do not remove table-level S
  and X locks and do not assert on such locks not being wait locks.
  Leave such locks alone.
  
  Approved by:	Heikki (rb://14)
  
  ------------------------------------------------------------------------
  r2710 | vasil | 2008-10-01 14:13:58 +0300 (Wed, 01 Oct 2008) | 6 lines
  Changed paths:
     M /branches/5.1/include/sync0sync.ic
  
  branches/5.1:
  
  Silence a compilation warning in UNIV_DEBUG.
  
  Approved by:	Marko (via IM)
  
  ------------------------------------------------------------------------
  r2719 | vasil | 2008-10-03 18:17:28 +0300 (Fri, 03 Oct 2008) | 49 lines
  Changed paths:
     M /branches/5.1/handler/ha_innodb.cc
     A /branches/5.1/mysql-test/innodb_bug39438-master.opt
     A /branches/5.1/mysql-test/innodb_bug39438.result
     A /branches/5.1/mysql-test/innodb_bug39438.test
  
  branches/5.1:
  
  Fix Bug#39438 Testcase for Bug#39436 crashes on 5.1 in fil_space_get_latch
  
  In ha_innobase::info() - do not try to get the free space for a tablespace
  which has been discarded with ALTER TABLE ... DISCARD TABLESPACE or if the
  .ibd file is missing for some other reason.
  
  ibd_file_missing and tablespace_discarded are manipulated only in
  row_discard_tablespace_for_mysql() and in row_import_tablespace_for_mysql()
  and the manipulation is protected/surrounded by
  row_mysql_lock_data_dictionary()/row_mysql_unlock_data_dictionary() thus we
  do the same in ha_innobase::info() when checking the values of those members
  to avoid race conditions. I have tested the code-path with UNIV_DEBUG and
  UNIV_SYNC_DEBUG.
  
  Looks like it is not possible to avoid mysqld printing warnings in the
  mysql-test case and thus this test innodb_bug39438 must be added to the
  list of exceptional test cases that are allowed to print warnings. For this,
  the following patch must be applied to the mysql source tree:
  
    --- cut ---
    === modified file 'mysql-test/lib/mtr_report.pl'
    --- mysql-test/lib/mtr_report.pl	2008-08-12 10:26:23 +0000
    +++ mysql-test/lib/mtr_report.pl	2008-10-01 11:57:41 +0000
    @@ -412,7 +412,10 @@
     
                     # When trying to set lower_case_table_names = 2
                     # on a case sensitive file system. Bug#37402.
    -                /lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive.  Now setting lower_case_table_names to 0 to avoid future problems./
    +                /lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive.  Now setting lower_case_table_names to 0 to avoid future problems./ or
    +
    +                # this test is expected to print warnings
    +                ($testname eq 'main.innodb_bug39438')
     		)
                 {
                   next;                       # Skip these lines
    
    --- cut ---
  
  The mysql-test is currently somewhat disabled (see inside
  innodb_bug39438.test), after the above patch has been applied to the mysql
  source tree, the test can be enabled.
  
  rb://20
  
  Reviewed by:	Inaam, Calvin
  Approved by:	Heikki
  
  ------------------------------------------------------------------------
  r2720 | vasil | 2008-10-03 19:52:39 +0300 (Fri, 03 Oct 2008) | 8 lines
  Changed paths:
     M /branches/5.1/handler/ha_innodb.cc
  
  branches/5.1:
  
  Print a warning if an attempt is made to get the free space for a table
  whose .ibd file is missing or the tablespace has been discarded. This is a
  followup to r2719.
  
  Suggested by:	Inaam
  
  ------------------------------------------------------------------------
  r2721 | sunny | 2008-10-04 02:08:23 +0300 (Sat, 04 Oct 2008) | 6 lines
  Changed paths:
     M /branches/5.1/handler/ha_innodb.cc
  
  branches/5.1: We need to send the messages to the client because
  handler::get_auto_increment() doesn't allow a way to return the
  specific error for why it failed.
  
  rb://18
  
  ------------------------------------------------------------------------
  r2722 | sunny | 2008-10-04 02:48:04 +0300 (Sat, 04 Oct 2008) | 18 lines
  Changed paths:
     M /branches/5.1/dict/dict0mem.c
     M /branches/5.1/handler/ha_innodb.cc
     M /branches/5.1/include/dict0mem.h
     M /branches/5.1/include/row0mysql.h
     M /branches/5.1/mysql-test/innodb-autoinc.result
     M /branches/5.1/mysql-test/innodb-autoinc.test
     M /branches/5.1/row/row0mysql.c
  
  branches/5.1: This bug has always existed but was masked by other errors. The
  fix for bug# 38839 triggered this bug. When the offset and increment are > 1
  we need to calculate the next value taking into consideration the two
  variables. Previously we simply assumed they were 1 particularly offset was
  never used. MySQL does its own calculation and that's probably why it seemed
  to work in the past. We would return what we thought was the correct next
  value and then MySQL would recalculate the actual value from that and return
  it to the caller (e.g., handler::write_row()). Several new tests have been
  added that try and catch some edge cases. The tests exposed a wrap around
  error in MySQL next value calculation which was filed as bug#39828. The tests
  will need to be updated once MySQL fix that bug.
  
  One good side effect of this fix is that dict_table_t size has been
  reduced by 8 bytes because we have moved the autoinc_increment field to
  the row_prebuilt_t structure. See review-board for a detailed discussion.
  
  rb://3
  
  ------------------------------------------------------------------------
2008-10-04 03:22:36 +00:00
marko
cdba733fb5 branches/zip: Merge 2263:2295 from branches/5.1. 2008-02-18 20:09:03 +00:00
marko
788650088b branches/zip: Add a UNIV_INTERN qualifier to every global function declaration
in *.h files, so that the function signatures in the *.h and *.c files fully
match each other.

ut_dulint_sort(): Add a UNIV_INTERN qualifier also to the function definition.
2008-02-18 18:38:33 +00:00
marko
d35922d15a branches/zip: Minor cleanup.
row_create_index_graph_for_mysql(): Move from row0mysql.c to row0merge.c
and rename to row_merge_create_index_graph().  Also change the function
comment to say that the function will create and execute the query graph
for creating the index.

row_merge_create_index(): Remove redundant assignment to trx->error_state.
2007-12-19 15:05:13 +00:00
marko
d0d9299177 branches/zip: Fast index creation: Remove the ROW_PREBUILT_OBSOLETE nonsense.
Active transactions must not switch table or index definitions on the fly,
for several reasons, including the following:

 * copied indexes do not carry any history or locking information;
   that is, rollbacks, read views, and record locking would be broken

 * huge potential for race conditions, inconsistent reads and writes,
   loss of data, and corruption

Instead of trying to track down if the table was changed during a transaction,
acquire appropriate locks that protect the creation and dropping of indexes.

innodb-index.test: Test the locking of CREATE INDEX and DROP INDEX.  Test
that consistent reads work across dropped indexes.

lock_rec_insert_check_and_lock(): Relax the lock_table_has() assertion.
When inserting a record into an index, the table must be at least IX-locked.
However, when an index is being created, an IS-lock on the table is
sufficient.

row_merge_lock_table(): Add the parameter enum lock_mode mode, which must
be LOCK_X or LOCK_S.

row_merge_drop_table(): Assert that n_mysql_handles_opened == 0.
Unconditionally drop the table.

ha_innobase::add_index(): Acquire an X or S lock on the table, as appropriate.
After acquiring an X lock, assert that n_mysql_handles_opened == 1.
Remove the comments about dropping tables in the background.

ha_innobase::final_drop_index(): Acquire an X lock on the table.

dict_table_t: Remove version_number, to_be_dropped, and prebuilts.
ins_node_t: Remove table_version_number.

enum lock_mode: Move the definition from lock0lock.h to lock0types.h.

ROW_PREBUILT_OBSOLETE, row_update_prebuilt(), row_prebuilt_table_obsolete():
Remove.

row_prebuilt_t: Remove the declaration from row0types.h.

row_drop_table_for_mysql_no_commit(): Always print a warning if a table
was added to the background drop queue.
2007-12-17 15:49:59 +00:00
marko
48d761aeb8 branches/zip: row_mysql_store_blob_ref(): Change the type of the parameter
"data" from byte* to const void*.
2007-09-27 10:59:54 +00:00
marko
52a8928693 branches/zip: Simplify crash recovery in fast index creation.
trx_t: Remove dict_undo_list and dict_redo_list.

innobase_create_temporary_tablename(): Replace TEMP_TABLE_PREFIX with
a table name suffix "#1" or "#2".  In this way, the user can restore
precious data, should anything go wrong.  It is possible to reach an
inconsistent state, because the creation, deletion and renaming of
single-table tablespaces are not transactional.

ut_print_namel(), fil_make_ibd_name(), innobase_rename_table(): Remove
the special treatment of TEMP_TABLE_PREFIX.

Introduce TEMP_INDEX_PREFIX == 0xff for temporary indexes.  This byte
cannot occur in index names since MySQL 4.1.  However, it might have
been possible to use this byte in MySQL 4.0.

recv_recovery_from_checkpoint_finish(): Call the new function
row_merge_drop_temp_indexes(), to drop all indexes whose name starts
with the byte 0xff.

row_merge_rename_indexes(): Renamed from row_merge_rename_index().
Remove the parameter "index".

row_drop_table_for_mysql(): Unconditionally call trx_commit_for_mysql().

row_drop_table_for_mysql_no_commit(): Correct the function commit,
based on the corrected comment of row_drop_table_for_mysql().  Rely on
table->to_be_dropped instead of TEMP_TABLE_PREFIX.

ha_innobase::add_index(): Simplify the control flow.
2007-09-05 10:18:03 +00:00
marko
faec4797c8 branches/zip: Merge 1664:1783 from trunk. 2007-08-30 09:21:25 +00:00
marko
0d6bfcb547 branches/zip: Fix a memory leak in fast index creation.
ha_innobase::add_index(): Add assertions about !trx->sync_cb and
!trx->dict_redo_list.  Remove a bogus comment.  Replace
row_lock_table_for_merge() with row_merge_lock_table().

row_merge_lock_table(): Renamed from row_lock_table_for_merge()
and moved from row0mysql.c to row0merge.c.  Always lock the table in
the mode LOCK_X.  Call que_graph_free() in order not to leak memory.
2007-08-21 12:10:14 +00:00
marko
3c680f7c44 branches/zip: Add some const qualifiers to dict_index_t* and dict_table_t*.
innobase_create_key_def(), row_table_got_default_clust_index(),
row_get_mysql_key_number_for_index(): Add a const qualifier.

dict_table_get_first_index(), dict_table_get_next_index(): Define
as a const-preserving macro.  Preserve the old function for UNIV_DEBUG,
but add a const qualifier to the parameter and cast away the constness.
2007-08-13 15:57:28 +00:00
marko
635d049d13 branches/zip: row_rename_table_for_mysql(): Change the return type to ulint
and simplify error handling.
2007-08-13 12:46:13 +00:00
marko
a3566c2c2d branches/zip: Add const qualifiers to the functions that read MySQL data.
row_mysql_read_true_varchar(), row_mysql_read_blob_ref(),
row_mysql_store_col_in_innobase_format(),
row_sel_convert_mysql_key_to_innobase(): Add const qualifiers.

row_sel_convert_mysql_key_to_innobase(): Document that the first parameter
is in/out.
2007-08-03 07:09:29 +00:00
marko
11665dc32a branches/zip: Ensure that the dictionary updates are atomic by keeping
the data dictionary locked across the operations.

dict_table_decrement_handle_count(), row_prebuilt_free(): Add the flag
dict_locked, to prevent the acquisition of dict_sys->mutex.

innobase_rename_table(): Rename commit_flag to lock_and_commit,
and do not acquire dict_sys->mutex or flush the log unless the flag is set.
Remove bogus comment about utility threads, because the threads will
be waken up by the upper-level function ha_innobase::rename_table().

ha_innobase::add_index(): After creating a primary key, hold dict_sys->mutex
across all dictionary operations.
2007-08-02 10:55:25 +00:00
marko
d662c3c656 branches/zip: Merge 1575:1664 from trunk. 2007-08-01 11:18:43 +00:00
marko
f839b3f390 branches/zip: Merge 1556:1571 from trunk. 2007-06-12 10:59:01 +00:00
marko
fd91f7bb76 branches/zip: Reimplement merge sort in fast index creation.
The creation of the primary key does not work.  We will have to flag
externally stored columns and copy the externally stored part from
the old table.

row_build_index_for_mysql(): Rename to row_merge_build_indexes().
Move from row0mysql.c to row0merge.c.

Remove private declarations from row0merge.h.  Make many functions static
in row0merge.c.

cmp_rec_rec_simple(): A new comparison function.

dict_index_get_min_size(): New function.

OS_FILE_FROM_FD(fd): A macro for converting from int to os_file_t.

rec_convert_dtuple_to_rec_comp(): Make the interface lower-level.

rec_get_converted_size_comp(): Return also extra_size.

UT_SORT_FUNCTION_BODY(): Remove reference to an obsolete test program.

row_rec_to_index_entry_low(): New function.

row0merge.c: Implement merge sort based on file streams instead of
fixed-size blocks.  Sort the small blocks as arrays of dfield_t*,
because it is faster than invoking rec_get_offsets() for every
comparison.
2007-06-08 07:37:07 +00:00
marko
1d2284c336 branches/zip: Minor cleanup.
row_merge_mark_prebuilt_obsolete(): Rename to row_prebuilt_table_obsolete()
and move from row0merge.c to row0mysql.c.  Remove the parameter trx.

row_merge_print_table(): Remove.
2007-06-04 07:51:10 +00:00
marko
d1bf0b7dab branches/zip: Minor cleanup.
row_remove_indexes_for_mysql(): Rename to row_merge_drop_indexes(),
move from row0mysql.c to row0merge.c and make the return type void.

row_merge_remove_index(): Rename to row_merge_drop_index() and make
the return type void.
2007-06-04 07:49:31 +00:00
marko
3f7aa60c81 branches/zip: Correct the terminology: s/cluster index/clustered index/.
row_merge_read_clustered_index(): Simplify the loop that scans the
clustered index.
2007-05-22 06:48:53 +00:00
marko
e7284367dc branches/zip: Merge revisions 1402:1493 from trunk.
Remove mysql.patch, because the configuration parameter interface has changed.
2007-05-14 09:07:15 +00:00
marko
96e9017471 branches/zip: More cleanup of fast index creation.
innobase_create_temporary_tablename(): Add static qualifier.  Allocate
the memory from heap.  Return a fixed identifier.

ha_innobase::add_index(): Allocate all memory from a single heap.
Simplify error handling.  Use a fixed prefix for temporary table names,
because only one add_index() can be active for a given table.

mem_heap_empty_noninline(): New function, to be called from ha_innodb.cc.

row_build_index_for_mysql(): Remove the parameter new_primary.
2007-04-12 05:14:41 +00:00
marko
a47b9e64e6 branches/zip: Merge branches/fast-index-creation -r1413.
Fix some bugs.  The tests innodb and innodb-index fail, but that might
be due to an old MySQL source tree being used.
2007-04-04 11:05:33 +00:00
marko
c712838401 branches/zip: Merge revisions 1165:1206 from trunk. 2007-01-18 12:58:39 +00:00
marko
4286b8286b branches/zip: Fix compilation errors when UNIV_HOTBACKUP is defined. 2006-11-30 15:25:52 +00:00
marko
64f3cee67f branches/zip: Merge revisions 720:765 from trunk and reindent the code
as per revisions r763:765.
2006-08-29 09:30:31 +00:00
marko
450bbd7c3b branches/zip: Merge revisions 265:459 from trunk. 2006-04-12 09:32:17 +00:00
marko
f40121415d branches/zip: Merge revisions 200:236 from trunk. 2006-02-23 19:25:29 +00:00
marko
6ce8427cb8 branches/zip: Merge revisions 79:200 from trunk. 2006-02-17 14:19:39 +00:00
osku
c307820962 Import 5.0 code. 2005-10-27 07:29:40 +00:00