From: Ole John Aske Date: April 11 2012 10:35am Subject: bzr push into mysql-5.5-cluster-7.2-spj branch (ole.john.aske:3860 to 3861) List-Archive: http://lists.mysql.com/commits/143452 Message-Id: <20120411103527.61422252@fimafeng09.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3861 Ole John Aske 2012-04-11 [merge] merge mysql-5.5-cluster-7.2 -> mysql-5.5-cluster-7.2-spj> modified: storage/ndb/include/util/Vector.hpp storage/ndb/memcache/extra/memcached/CMakeLists.txt storage/ndb/memcache/extra/memcached/config_tests.in storage/ndb/memcache/extra/memcached/daemon/memcached.c storage/ndb/memcache/include/Scheduler.h storage/ndb/memcache/include/ndb_engine.h storage/ndb/memcache/include/ndb_engine_errors.h storage/ndb/memcache/include/ndb_pipeline.h storage/ndb/memcache/include/ndbmemcache_config.in storage/ndb/memcache/src/ExternalValue.cc storage/ndb/memcache/src/ndb_engine.c storage/ndb/memcache/src/ndb_engine_errors.cc storage/ndb/memcache/src/ndb_error_logger.cc storage/ndb/memcache/src/ndb_pipeline.cc storage/ndb/memcache/src/ndb_worker.cc storage/ndb/memcache/src/schedulers/S_sched.cc storage/ndb/memcache/src/schedulers/S_sched.h storage/ndb/memcache/src/schedulers/Stockholm.cc storage/ndb/memcache/src/schedulers/Stockholm.h storage/ndb/memcache/unit/alloc.cc storage/ndb/src/ndbapi/NdbQueryBuilder.cpp storage/ndb/src/ndbapi/NdbQueryOperation.cpp storage/ndb/test/CMakeLists.txt 3860 Jan Wedvik 2012-03-30 [merge] Merged from mysql-5.5-cluster-7.2. added: extra/yassl/certs/ca-key.pem extra/yassl/certs/client-keyEnc.pem extra/yassl/certs/client-keyEnc3.pem extra/yassl/certs/server-keyEnc.pem extra/yassl/taocrypt/certs/ extra/yassl/taocrypt/certs/client-cert.der extra/yassl/taocrypt/certs/client-key.der extra/yassl/taocrypt/certs/dh1024.dat extra/yassl/taocrypt/certs/dsa512.der extra/yassl/taocrypt/include/hc128.hpp extra/yassl/taocrypt/include/rabbit.hpp extra/yassl/taocrypt/src/hc128.cpp extra/yassl/taocrypt/src/rabbit.cpp mysql-test/include/libdaemon_example.ini mysql-test/r/bug13633383.result mysql-test/suite/innodb/r/innodb-blob.result mysql-test/suite/innodb/r/innodb_bug11754376.result mysql-test/suite/innodb/r/innodb_bug12400341.result mysql-test/suite/innodb/r/innodb_bug13510739.result mysql-test/suite/innodb/t/innodb-blob.test mysql-test/suite/innodb/t/innodb_bug11754376.test mysql-test/suite/innodb/t/innodb_bug12400341-master.opt mysql-test/suite/innodb/t/innodb_bug12400341.test mysql-test/suite/innodb/t/innodb_bug13510739.test mysql-test/suite/ndb/backups/wl946_pre/ mysql-test/suite/ndb/backups/wl946_pre/BACKUP-1-0.1.Data mysql-test/suite/ndb/backups/wl946_pre/BACKUP-1-0.2.Data mysql-test/suite/ndb/backups/wl946_pre/BACKUP-1.1.ctl mysql-test/suite/ndb/backups/wl946_pre/BACKUP-1.1.log mysql-test/suite/ndb/backups/wl946_pre/BACKUP-1.2.ctl mysql-test/suite/ndb/backups/wl946_pre/BACKUP-1.2.log mysql-test/suite/ndb/data/wl946_pre.dat mysql-test/suite/ndb/r/ndb_wl946_pre.result mysql-test/suite/ndb/t/ndb_wl946_create.inc mysql-test/suite/ndb/t/ndb_wl946_pre.test mysql-test/suite/ndb/t/ndb_wl946_pre_query.inc mysql-test/suite/ndb/t/show_indexes.inc mysql-test/suite/ndb_binlog/r/ndb_binlog_index.result mysql-test/suite/ndb_binlog/t/ndb_binlog_check_binlog_index.inc mysql-test/suite/ndb_binlog/t/ndb_binlog_index.test mysql-test/suite/ndb_binlog/t/ndb_binlog_index_test_schema_independent.inc mysql-test/suite/rpl/r/rpl_skip_ddl_errors_cli.result mysql-test/suite/rpl/r/rpl_start_stop_slave.result mysql-test/suite/rpl/t/rpl_skip_ddl_errors_cli-slave.opt mysql-test/suite/rpl/t/rpl_skip_ddl_errors_cli.test mysql-test/suite/rpl/t/rpl_start_stop_slave.test mysql-test/suite/sys_vars/r/innodb_change_buffering_debug_basic.result mysql-test/suite/sys_vars/r/innodb_trx_rseg_n_slots_debug_basic.result mysql-test/suite/sys_vars/r/stored_program_cache_basic.result mysql-test/suite/sys_vars/t/innodb_change_buffering_debug_basic.test mysql-test/suite/sys_vars/t/innodb_trx_rseg_n_slots_debug_basic.test mysql-test/suite/sys_vars/t/stored_program_cache_basic.test mysql-test/t/bug13633383.test storage/ndb/src/ndbjtie/com/mysql/ndbjtie/ndbapi/NDBAPIConst.java modified: .bzrignore CMakeLists.txt INSTALL-SOURCE INSTALL-WIN-SOURCE README VERSION client/CMakeLists.txt client/mysql_plugin.c client/mysql_upgrade.c client/mysqldump.c client/sql_string.cc cmake/build_configurations/mysql_release.cmake cmake/install_macros.cmake cmake/mysql_version.cmake cmake/package_name.cmake extra/yassl/INSTALL extra/yassl/README extra/yassl/certs/ca-cert.pem extra/yassl/certs/client-cert.der extra/yassl/certs/client-cert.pem extra/yassl/certs/client-key.der extra/yassl/certs/client-key.pem extra/yassl/certs/dsa-cert.pem extra/yassl/certs/dsa512.der extra/yassl/certs/server-cert.pem extra/yassl/certs/server-key.pem extra/yassl/certs/taoCert.txt extra/yassl/examples/client/client.cpp extra/yassl/examples/echoclient/echoclient.cpp extra/yassl/examples/echoserver/echoserver.cpp extra/yassl/examples/server/server.cpp extra/yassl/include/buffer.hpp extra/yassl/include/openssl/ssl.h extra/yassl/include/socket_wrapper.hpp extra/yassl/include/yassl_int.hpp extra/yassl/include/yassl_types.hpp extra/yassl/src/buffer.cpp extra/yassl/src/cert_wrapper.cpp extra/yassl/src/crypto_wrapper.cpp extra/yassl/src/handshake.cpp extra/yassl/src/make.bat* extra/yassl/src/socket_wrapper.cpp extra/yassl/src/ssl.cpp extra/yassl/src/yassl.cpp extra/yassl/src/yassl_error.cpp extra/yassl/src/yassl_imp.cpp extra/yassl/src/yassl_int.cpp extra/yassl/taocrypt/CMakeLists.txt extra/yassl/taocrypt/README extra/yassl/taocrypt/benchmark/benchmark.cpp extra/yassl/taocrypt/benchmark/benchmark.dsp extra/yassl/taocrypt/benchmark/dh1024.der extra/yassl/taocrypt/benchmark/dsa1024.der extra/yassl/taocrypt/benchmark/make.bat* extra/yassl/taocrypt/benchmark/rsa1024.der extra/yassl/taocrypt/include/asn.hpp extra/yassl/taocrypt/include/block.hpp extra/yassl/taocrypt/include/blowfish.hpp extra/yassl/taocrypt/include/des.hpp extra/yassl/taocrypt/include/file.hpp extra/yassl/taocrypt/include/hash.hpp extra/yassl/taocrypt/include/integer.hpp extra/yassl/taocrypt/include/kernelc.hpp extra/yassl/taocrypt/include/misc.hpp extra/yassl/taocrypt/include/modes.hpp extra/yassl/taocrypt/include/pwdbased.hpp extra/yassl/taocrypt/include/rsa.hpp extra/yassl/taocrypt/include/runtime.hpp extra/yassl/taocrypt/include/types.hpp extra/yassl/taocrypt/mySTL/stdexcept.hpp extra/yassl/taocrypt/mySTL/vector.hpp extra/yassl/taocrypt/src/aes.cpp extra/yassl/taocrypt/src/aestables.cpp extra/yassl/taocrypt/src/algebra.cpp extra/yassl/taocrypt/src/arc4.cpp extra/yassl/taocrypt/src/asn.cpp extra/yassl/taocrypt/src/blowfish.cpp extra/yassl/taocrypt/src/coding.cpp extra/yassl/taocrypt/src/dsa.cpp extra/yassl/taocrypt/src/hash.cpp extra/yassl/taocrypt/src/integer.cpp extra/yassl/taocrypt/src/make.bat* extra/yassl/taocrypt/src/md4.cpp extra/yassl/taocrypt/src/md5.cpp extra/yassl/taocrypt/src/misc.cpp extra/yassl/taocrypt/src/random.cpp extra/yassl/taocrypt/src/ripemd.cpp extra/yassl/taocrypt/src/rsa.cpp extra/yassl/taocrypt/src/sha.cpp extra/yassl/taocrypt/src/template_instnt.cpp extra/yassl/taocrypt/src/twofish.cpp extra/yassl/taocrypt/taocrypt.dsp extra/yassl/taocrypt/test/make.bat* extra/yassl/taocrypt/test/memory.cpp extra/yassl/taocrypt/test/test.cpp extra/yassl/testsuite/make.bat* extra/yassl/testsuite/test.hpp extra/yassl/testsuite/testsuite.cpp include/m_ctype.h include/m_string.h include/my_global.h include/myisam.h include/mysql/plugin.h include/welcome_copyright_notice.h libmysql/CMakeLists.txt libmysqld/CMakeLists.txt libmysqld/examples/CMakeLists.txt man/CMakeLists.txt mysql-test/CMakeLists.txt mysql-test/collections/default.experimental mysql-test/extra/rpl_tests/rpl_extra_col_master.test mysql-test/extra/rpl_tests/rpl_insert_id_pk.test mysql-test/extra/rpl_tests/rpl_multi_update.test mysql-test/extra/rpl_tests/rpl_multi_update2.test mysql-test/extra/rpl_tests/rpl_multi_update3.test mysql-test/extra/rpl_tests/rpl_start_stop_slave.test mysql-test/include/have_32bit.inc mysql-test/include/have_example_plugin.inc mysql-test/include/have_semisync_plugin.inc mysql-test/include/have_simple_parser.inc mysql-test/include/have_udf.inc mysql-test/include/mtr_check.sql mysql-test/include/show_slave_status.inc mysql-test/include/wait_for_slave_io_error.inc mysql-test/mysql-stress-test.pl mysql-test/mysql-test-run.pl mysql-test/r/bigint.result mysql-test/r/ctype_utf8.result mysql-test/r/func_in.result mysql-test/r/func_str.result mysql-test/r/func_time.result mysql-test/r/init_connect.result mysql-test/r/join_outer.result mysql-test/r/multi_update.result mysql-test/r/myisam.result mysql-test/r/mysql_plugin.result mysql-test/r/mysqld--help-notwin.result mysql-test/r/mysqld--help-win.result mysql-test/r/mysqldump.result mysql-test/r/partition.result mysql-test/r/partition_binlog_stmt.result mysql-test/r/partition_error.result mysql-test/r/ps.result mysql-test/r/range.result mysql-test/r/sp-bugs.result mysql-test/r/sp.result mysql-test/r/xa.result mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result mysql-test/suite/binlog/r/binlog_unsafe.result mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test mysql-test/suite/binlog/t/binlog_unsafe.test mysql-test/suite/engines/funcs/r/db_alter_collate_ascii.result mysql-test/suite/engines/funcs/r/db_alter_collate_utf8.result mysql-test/suite/funcs_1/r/is_columns_mysql.result mysql-test/suite/innodb/r/innodb-index.result mysql-test/suite/innodb/t/innodb-index.test mysql-test/suite/innodb/t/innodb_bug34300.test mysql-test/suite/innodb/t/innodb_bug53756.test mysql-test/suite/ndb/include/ndb_share_check_shares.inc mysql-test/suite/ndb/r/ndb_basic.result mysql-test/suite/ndb/r/ndb_ddl_open_trans.result mysql-test/suite/ndb/r/ndb_index_stat_restart.result mysql-test/suite/ndb/r/ndb_share.result mysql-test/suite/ndb/t/ndb_basic.test mysql-test/suite/ndb/t/ndb_ddl_open_trans.test mysql-test/suite/ndb/t/ndb_index_stat_restart.test mysql-test/suite/ndb_binlog/r/ndb_binlog_ignore_db.result mysql-test/suite/ndb_binlog/t/ndb_binlog_ignore_db.test mysql-test/suite/ndb_rpl/r/ndb_rpl_ddl_open_trans.result mysql-test/suite/ndb_rpl/r/ndb_rpl_idempotent.result mysql-test/suite/ndb_rpl/r/ndb_rpl_sync.result mysql-test/suite/ndb_rpl/t/ndb_rpl_idempotent.test mysql-test/suite/rpl/r/rpl_auto_increment_11932.result mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result mysql-test/suite/rpl/r/rpl_heartbeat_basic.result mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result mysql-test/suite/rpl/r/rpl_insert_id_pk.result mysql-test/suite/rpl/r/rpl_known_bugs_detection.result mysql-test/suite/rpl/r/rpl_log_pos.result mysql-test/suite/rpl/r/rpl_manual_change_index_file.result mysql-test/suite/rpl/r/rpl_multi_update.result mysql-test/suite/rpl/r/rpl_multi_update2.result mysql-test/suite/rpl/r/rpl_multi_update3.result mysql-test/suite/rpl/r/rpl_packet.result mysql-test/suite/rpl/r/rpl_rotate_logs.result mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result mysql-test/suite/rpl/t/rpl_auto_increment_11932.test mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test mysql-test/suite/rpl/t/rpl_heartbeat_basic.test mysql-test/suite/rpl/t/rpl_known_bugs_detection.test mysql-test/suite/rpl/t/rpl_log_pos.test mysql-test/suite/rpl/t/rpl_manual_change_index_file.test mysql-test/suite/rpl/t/rpl_multi_update2.test mysql-test/suite/rpl/t/rpl_multi_update3.test mysql-test/suite/rpl/t/rpl_optimize.test mysql-test/suite/rpl/t/rpl_packet.test mysql-test/suite/rpl/t/rpl_rotate_logs.test mysql-test/suite/rpl/t/rpl_semi_sync_event.test mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test mysql-test/suite/rpl/t/rpl_timezone.test mysql-test/suite/sys_vars/r/all_vars.result mysql-test/suite/sys_vars/r/character_sets_dir_basic.result mysql-test/suite/sys_vars/r/plugin_dir_basic.result mysql-test/suite/sys_vars/t/all_vars.test mysql-test/suite/sys_vars/t/character_sets_dir_basic.test mysql-test/suite/sys_vars/t/disabled.def mysql-test/t/bigint.test mysql-test/t/ctype_utf8.test mysql-test/t/events_restart.test mysql-test/t/func_str.test mysql-test/t/func_time.test mysql-test/t/init_connect.test mysql-test/t/join_outer.test mysql-test/t/multi_update.test mysql-test/t/myisam.test mysql-test/t/mysql_plugin.test mysql-test/t/mysqldump.test mysql-test/t/partition.test mysql-test/t/partition_binlog_stmt.test mysql-test/t/partition_error.test mysql-test/t/ps.test mysql-test/t/range.test mysql-test/t/sp-bugs.test mysql-test/t/sp.test mysql-test/t/udf_skip_grants-master.opt mysql-test/t/xa.test mysql-test/valgrind.supp mysys/charset-def.c mysys/my_init.c mysys/my_symlink.c packaging/WiX/custom_ui.wxs plugin/auth/dialog.c plugin/auth/qa_auth_interface.c plugin/auth/qa_auth_server.c plugin/daemon_example/CMakeLists.txt plugin/daemon_example/daemon_example.cc scripts/mysql_install_db.pl.in scripts/mysql_install_db.sh scripts/mysql_system_tables.sql scripts/mysql_system_tables_fix.sql scripts/mysqld_safe.sh sql-common/my_time.c sql/filesort.cc sql/ha_ndbcluster.cc sql/ha_ndbcluster_binlog.cc sql/ha_partition.cc sql/item.cc sql/item_cmpfunc.cc sql/item_cmpfunc.h sql/item_timefunc.cc sql/item_xmlfunc.cc sql/log.cc sql/log.h sql/log_event.h sql/mysqld.cc sql/mysqld.h sql/rpl_handler.h sql/rpl_injector.cc sql/rpl_injector.h sql/rpl_mi.cc sql/rpl_mi.h sql/rpl_rli.cc sql/rpl_rli.h sql/set_var.h sql/share/errmsg-utf8.txt sql/slave.cc sql/slave.h sql/sp_cache.cc sql/sp_cache.h sql/sp_head.cc sql/sp_head.h sql/sql_admin.cc sql/sql_base.cc sql/sql_cache.cc sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_parse.cc sql/sql_partition.cc sql/sql_partition.h sql/sql_plugin.cc sql/sql_prepare.cc sql/sql_profile.cc sql/sql_repl.cc sql/sql_select.cc sql/sql_show.cc sql/sql_table.cc sql/sql_udf.cc sql/sql_yacc.yy sql/sys_vars.cc sql/sys_vars.h sql/table.h storage/archive/ha_archive.cc storage/blackhole/ha_blackhole.cc storage/csv/ha_tina.cc storage/example/ha_example.cc storage/federated/ha_federated.cc storage/heap/hp_info.c storage/innobase/btr/btr0btr.c storage/innobase/btr/btr0cur.c storage/innobase/btr/btr0pcur.c storage/innobase/btr/btr0sea.c storage/innobase/buf/buf0buf.c storage/innobase/buf/buf0flu.c storage/innobase/dict/dict0load.c storage/innobase/fil/fil0fil.c storage/innobase/fsp/fsp0fsp.c storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innobase/handler/handler0alter.cc storage/innobase/ibuf/ibuf0ibuf.c storage/innobase/include/btr0btr.h storage/innobase/include/btr0btr.ic storage/innobase/include/btr0cur.h storage/innobase/include/btr0cur.ic storage/innobase/include/btr0pcur.h storage/innobase/include/buf0buf.h storage/innobase/include/buf0buf.ic storage/innobase/include/data0data.h storage/innobase/include/data0data.ic storage/innobase/include/fsp0fsp.h storage/innobase/include/log0log.h storage/innobase/include/mem0mem.ic storage/innobase/include/mtr0log.ic storage/innobase/include/mtr0mtr.h storage/innobase/include/mtr0mtr.ic storage/innobase/include/page0page.h storage/innobase/include/page0page.ic storage/innobase/include/row0mysql.h storage/innobase/include/row0sel.h storage/innobase/include/sync0sync.h storage/innobase/include/trx0rec.ic storage/innobase/include/trx0rseg.ic storage/innobase/include/trx0sys.h storage/innobase/include/trx0undo.h storage/innobase/include/univ.i storage/innobase/include/ut0mem.h storage/innobase/include/ut0rnd.ic storage/innobase/lock/lock0lock.c storage/innobase/log/log0log.c storage/innobase/mem/mem0pool.c storage/innobase/mtr/mtr0mtr.c storage/innobase/os/os0file.c storage/innobase/os/os0proc.c storage/innobase/page/page0cur.c storage/innobase/page/page0page.c storage/innobase/pars/pars0pars.c storage/innobase/row/row0ins.c storage/innobase/row/row0merge.c storage/innobase/row/row0mysql.c storage/innobase/row/row0row.c storage/innobase/row/row0sel.c storage/innobase/row/row0umod.c storage/innobase/row/row0upd.c storage/innobase/srv/srv0srv.c storage/innobase/srv/srv0start.c storage/innobase/sync/sync0rw.c storage/innobase/sync/sync0sync.c storage/innobase/trx/trx0purge.c storage/innobase/trx/trx0rec.c storage/innobase/trx/trx0sys.c storage/innobase/trx/trx0trx.c storage/innobase/trx/trx0undo.c storage/innobase/ut/ut0mem.c storage/myisam/ft_boolean_search.c storage/myisam/ft_nlq_search.c storage/myisam/ha_myisam.cc storage/myisam/ha_myisam.h storage/myisam/mi_check.c storage/myisam/mi_packrec.c storage/myisam/mi_preload.c storage/myisam/myisamchk.c storage/myisam/myisamdef.h storage/myisam/sort.c storage/ndb/clusterj/clusterj-api/pom.xml storage/ndb/clusterj/clusterj-bindings/pom.xml storage/ndb/clusterj/clusterj-core/pom.xml storage/ndb/clusterj/clusterj-jdbc/pom.xml storage/ndb/clusterj/clusterj-jpatest/pom.xml storage/ndb/clusterj/clusterj-openjpa/pom.xml storage/ndb/clusterj/clusterj-test/pom.xml storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/VarcharStringLengthTest.java storage/ndb/clusterj/clusterj-tie/pom.xml storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/OperationImpl.java storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/Utility.java storage/ndb/clusterj/clusterj-tie/src/main/resources/com/mysql/clusterj/tie/Bundle.properties storage/ndb/clusterj/pom.xml storage/ndb/memcache/include/NdbInstance.h storage/ndb/memcache/include/ndb_engine_errors.h storage/ndb/memcache/include/ndb_pipeline.h storage/ndb/memcache/src/ExternalValue.cc storage/ndb/memcache/src/NdbInstance.cc storage/ndb/memcache/src/ndb_configuration.cc storage/ndb/memcache/src/ndb_engine.c storage/ndb/memcache/src/ndb_engine_errors.cc storage/ndb/memcache/src/ndb_worker.cc storage/ndb/src/mgmsrv/ConfigManager.cpp storage/ndb/src/ndbapi/NdbQueryBuilder.cpp storage/ndb/src/ndbapi/NdbQueryBuilder.hpp storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp storage/ndb/src/ndbapi/NdbQueryOperation.cpp storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp storage/ndb/src/ndbjtie/com/mysql/ndbjtie/ndbapi/NDBAPI.java storage/ndb/src/ndbjtie/com/mysql/ndbjtie/ndbapi/NdbIndexScanOperation.java storage/ndb/src/ndbjtie/ndbapi_jtie.hpp storage/ndb/test/ndbapi/testMgmd.cpp storage/ndb/tools/ndb_size.pl storage/perfschema/ha_perfschema.cc storage/perfschema/pfs.cc storage/perfschema/table_ews_global_by_event_name.cc storage/perfschema/table_ews_global_by_event_name.h strings/ctype-uca.c strings/ctype-ucs2.c strings/ctype-utf8.c strings/dtoa.c support-files/compiler_warnings.supp unittest/mysys/bitmap-t.c unittest/mysys/my_atomic-t.c unittest/strings/strings-t.c === modified file 'storage/ndb/include/util/Vector.hpp' --- a/storage/ndb/include/util/Vector.hpp 2011-09-02 09:16:56 +0000 +++ b/storage/ndb/include/util/Vector.hpp 2012-04-11 08:45:06 +0000 @@ -24,7 +24,8 @@ template class Vector { public: - Vector(int sz = 10); + Vector(unsigned sz = 10, unsigned inc_sz = 0); + int expand(unsigned sz); ~Vector(); T& operator[](unsigned i); @@ -32,7 +33,7 @@ public: unsigned size() const { return m_size; }; int push_back(const T &); - void push(const T&, unsigned pos); + int push(const T&, unsigned pos); T& set(T&, unsigned pos, T& fill_obj); T& back(); @@ -63,40 +64,80 @@ private: unsigned m_arraySize; }; -template -Vector::Vector(int i){ - m_items = new T[i]; +/** + * BEWARE: Constructing Vector with initial size > 0 is + * unsafe wrt. catching 'out of memory' errors. + * (C'tor doesn't return error code) + * Instead construct Vector with size==0, and then + * expand() it to the wanted initial size. + */ +template +Vector::Vector(unsigned sz, unsigned inc_sz): + m_items(NULL), + m_size(0), + m_incSize((inc_sz > 0) ? inc_sz : 50), + m_arraySize(0) +{ + if (sz == 0) + return; + + m_items = new T[sz]; if (m_items == NULL) { errno = ENOMEM; - m_size = 0; - m_arraySize = 0; - m_incSize = 0; return; } - m_size = 0; - m_arraySize = i; - m_incSize = 50; + m_arraySize = sz; +} + +template +int +Vector::expand(unsigned sz){ + if (sz <= m_size) + return 0; + + T * tmp = new T[sz]; + if(tmp == NULL) + { + errno = ENOMEM; + return -1; + } + for (unsigned i = 0; i < m_size; i++) + tmp[i] = m_items[i]; + delete[] m_items; + m_items = tmp; + m_arraySize = sz; + return 0; } +/** + * BEWARE: Copy-constructing a Vector is + * unsafe wrt. catching 'out of memory' errors. + * (C'tor doesn't return error code) + * Instead construct empty Vector (size==0), + * and then assign() it the initial contents. + */ template Vector::Vector(const Vector& src): - m_items(new T[src.m_size]), - m_size(src.m_size), + m_items(NULL), + m_size(0), m_incSize(src.m_incSize), - m_arraySize(src.m_size) - + m_arraySize(0) { + const unsigned sz = src.m_size; + if (sz == 0) + return; + + m_items = new T[sz]; if (unlikely(m_items == NULL)){ errno = ENOMEM; - m_size = 0; - m_arraySize = 0; - m_incSize = 0; return; } - for(unsigned i = 0; i < m_size; i++){ + for(unsigned i = 0; i < sz; i++){ m_items[i] = src.m_items[i]; } + m_arraySize = sz; + m_size = sz; } template @@ -127,6 +168,8 @@ Vector::operator[](unsigned i) const template T & Vector::back(){ + if(m_size==0) + abort(); return (* this)[m_size - 1]; } @@ -134,17 +177,9 @@ template int Vector::push_back(const T & t){ if(m_size == m_arraySize){ - T * tmp = new T [m_arraySize + m_incSize]; - if(tmp == NULL) - { - errno = ENOMEM; - return -1; - } - for (unsigned k = 0; k < m_size; k++) - tmp[k] = m_items[k]; - delete[] m_items; - m_items = tmp; - m_arraySize = m_arraySize + m_incSize; + const int err = expand(m_arraySize + m_incSize); + if (unlikely(err)) + return err; } m_items[m_size] = t; m_size++; @@ -152,10 +187,12 @@ Vector::push_back(const T & t){ } template -void +int Vector::push(const T & t, unsigned pos) { - push_back(t); + const int err = push_back(t); + if (unlikely(err)) + return err; if (pos < m_size - 1) { for(unsigned i = m_size - 1; i > pos; i--) @@ -164,13 +201,15 @@ Vector::push(const T & t, unsigned po } m_items[pos] = t; } + return 0; } template T& Vector::set(T & t, unsigned pos, T& fill_obj) { - fill(pos, fill_obj); + if (fill(pos, fill_obj)) + abort(); T& ret = m_items[pos]; m_items[pos] = t; return ret; @@ -196,19 +235,31 @@ Vector::clear(){ template int Vector::fill(unsigned new_size, T & obj){ + const int err = expand(new_size); + if (unlikely(err)) + return err; while(m_size <= new_size) if (push_back(obj)) return -1; return 0; } +/** + * 'operator=' will 'abort()' on 'out of memory' errors. + * You may prefer using ::assign()' which returns + * an error code instead of aborting. + */ template Vector& Vector::operator=(const Vector& obj){ if(this != &obj){ clear(); + const int err = expand(obj.size()); + if (unlikely(err)) + abort(); for(unsigned i = 0; i int Vector::assign(const T* src, unsigned cnt) { + if (getBase() == src) + return 0; // Self-assign is a NOOP + clear(); + const int err = expand(cnt); + if (unlikely(err)) + return err; + for (unsigned i = 0; i::equal(const Vector& obj) c template class MutexVector : public NdbLockable { public: - MutexVector(int sz = 10); + MutexVector(unsigned sz = 10, unsigned inc_sz = 0); + int expand(unsigned sz); ~MutexVector(); T& operator[](unsigned i); @@ -260,26 +319,60 @@ public: int fill(unsigned new_size, T & obj); private: + // Don't allow copy and assignment of MutexVector + MutexVector(const MutexVector&); + MutexVector& operator=(const MutexVector&); + T * m_items; unsigned m_size; unsigned m_incSize; unsigned m_arraySize; }; -template -MutexVector::MutexVector(int i){ - m_items = new T[i]; +/** + * BEWARE: Constructing MutexVector with initial size > 0 is + * unsafe wrt. catching 'out of memory' errors. + * (C'tor doesn't return error code) + * Instead construct MutexVector with size==0, and then + * expand() it to the wanted initial size. + */ +template +MutexVector::MutexVector(unsigned sz, unsigned inc_sz): + m_items(NULL), + m_size(0), + m_incSize((inc_sz > 0) ? inc_sz : 50), + m_arraySize(0) +{ + if (sz == 0) + return; + + m_items = new T[sz]; if (m_items == NULL) { errno = ENOMEM; - m_size = 0; - m_arraySize = 0; - m_incSize = 0; return; } - m_size = 0; - m_arraySize = i; - m_incSize = 50; + m_arraySize = sz; +} + +template +int +MutexVector::expand(unsigned sz){ + if (sz <= m_size) + return 0; + + T * tmp = new T[sz]; + if(tmp == NULL) + { + errno = ENOMEM; + return -1; + } + for (unsigned i = 0; i < m_size; i++) + tmp[i] = m_items[i]; + delete[] m_items; + m_items = tmp; + m_arraySize = sz; + return 0; } template @@ -310,6 +403,8 @@ MutexVector::operator[](unsigned i) c template T & MutexVector::back(){ + if(m_size==0) + abort(); return (* this)[m_size - 1]; } @@ -318,18 +413,12 @@ int MutexVector::push_back(const T & t){ lock(); if(m_size == m_arraySize){ - T * tmp = new T [m_arraySize + m_incSize]; - if (tmp == NULL) + const int err = expand(m_arraySize + m_incSize); + if (unlikely(err)) { - errno = ENOMEM; unlock(); - return -1; + return err; } - for (unsigned k = 0; k < m_size; k++) - tmp[k] = m_items[k]; - delete[] m_items; - m_items = tmp; - m_arraySize = m_arraySize + m_incSize; } m_items[m_size] = t; m_size++; @@ -343,19 +432,13 @@ MutexVector::push_back(const T & t, b if(lockMutex) lock(); if(m_size == m_arraySize){ - T * tmp = new T [m_arraySize + m_incSize]; - if (tmp == NULL) + const int err = expand(m_arraySize + m_incSize); + if (unlikely(err)) { - errno = ENOMEM; if(lockMutex) unlock(); - return -1; + return err; } - for (unsigned k = 0; k < m_size; k++) - tmp[k] = m_items[k]; - delete[] m_items; - m_items = tmp; - m_arraySize = m_arraySize + m_incSize; } m_items[m_size] = t; m_size++; === modified file 'storage/ndb/memcache/extra/memcached/CMakeLists.txt' --- a/storage/ndb/memcache/extra/memcached/CMakeLists.txt 2011-09-23 00:00:18 +0000 +++ b/storage/ndb/memcache/extra/memcached/CMakeLists.txt 2012-03-31 15:10:44 +0000 @@ -84,6 +84,7 @@ CHECK_INCLUDE_FILE("netdb.h" HAV CHECK_INCLUDE_FILE("sys/uio.h" HAVE_SYS_UIO_H) CHECK_INCLUDE_FILE("signal.h" HAVE_SIGIGNORE) CHECK_INCLUDE_FILES("sys/types.h;netinet/tcp.h" HAVE_NETINET_TCP_H) +CHECK_FUNCTION_EXISTS(htonll HAVE_HTONLL) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config_tests.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h) === modified file 'storage/ndb/memcache/extra/memcached/config_tests.in' --- a/storage/ndb/memcache/extra/memcached/config_tests.in 2011-09-20 05:13:01 +0000 +++ b/storage/ndb/memcache/extra/memcached/config_tests.in 2012-03-31 15:16:18 +0000 @@ -24,6 +24,7 @@ #cmakedefine HAVE_SYS_UIO_H #cmakedefine HAVE_NETINET_TCP_H #cmakedefine HAVE_SIGIGNORE +#cmakedefine HAVE_HTONLL #include "my_config.h" #include "config_static.h" === modified file 'storage/ndb/memcache/extra/memcached/daemon/memcached.c' --- a/storage/ndb/memcache/extra/memcached/daemon/memcached.c 2011-09-20 05:13:01 +0000 +++ b/storage/ndb/memcache/extra/memcached/daemon/memcached.c 2012-04-06 00:06:41 +0000 @@ -1761,6 +1761,10 @@ static void process_bin_get(conn *c) { case ENGINE_NOT_MY_VBUCKET: write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET, 0); break; + case ENGINE_TMPFAIL: + write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_ETMPFAIL, 0); + break; + default: /* @todo add proper error handling! */ settings.extensions.logger->log(EXTENSION_LOG_WARNING, c, === modified file 'storage/ndb/memcache/include/Scheduler.h' --- a/storage/ndb/memcache/include/Scheduler.h 2012-03-07 01:22:53 +0000 +++ b/storage/ndb/memcache/include/Scheduler.h 2012-04-03 00:34:18 +0000 @@ -23,13 +23,21 @@ #include "ndbmemcache_global.h" #include -#include "ndb_pipeline.h" +#include "thread_identifier.h" + + +typedef struct { + int nthreads; /* number of worker threads */ + int max_clients; /* maximum number of client connections */ + const char * config_string; /* scheduler-specific configuration string */ +} scheduler_options; + #ifdef __cplusplus -#include "NdbInstance.h" -#include "Configuration.h" -#include "thread_identifier.h" +/* Forward declarations */ +class Configuration; +class workitem; /* Scheduler is an interface */ @@ -44,10 +52,9 @@ public: /** init() is the called from the main thread, after configuration has been read. threadnum: which thread this scheduler will eventually attach to - nthreads: how many total threads will be initialized - config_string: additional configuration string for scheduler + options: struct specifying run-time options */ - virtual void init(int threadnum, int nthreads, const char *config_string) = 0; + virtual void init(int threadnum, const scheduler_options * options) = 0; /** attach_thread() is called from each thread at pipeline initialization time. */ @@ -87,9 +94,6 @@ public: */ virtual bool global_reconfigure(Configuration *new_config) = 0; - /** each scheduler instance serves a single NDB pipeline - */ - ndb_pipeline *pipeline; }; #endif === modified file 'storage/ndb/memcache/include/ndb_engine.h' --- a/storage/ndb/memcache/include/ndb_engine.h 2012-03-07 01:22:53 +0000 +++ b/storage/ndb/memcache/include/ndb_engine.h 2012-04-03 00:34:18 +0000 @@ -62,6 +62,7 @@ struct ndb_engine { } startup_options; struct { + size_t maxconns; size_t nthreads; bool cas_enabled; size_t verbose; === modified file 'storage/ndb/memcache/include/ndb_engine_errors.h' --- a/storage/ndb/memcache/include/ndb_engine_errors.h 2012-03-23 19:01:07 +0000 +++ b/storage/ndb/memcache/include/ndb_engine_errors.h 2012-04-05 21:37:02 +0000 @@ -22,11 +22,22 @@ #include -/* Errors 9000 - 9099 are reported as "Scheduler Error" */ -extern ndberror_struct AppError9001_ReconfLock; -extern ndberror_struct AppError9002_NoNDBs; -extern ndberror_struct AppError9003_SyncClose; +/* + The NDB Engine for Memcached uses error codes 29000 - 29999 +*/ -/* Errors 9100 and up are reported as "Memcached Error" */ + + +/*** Errors 290xx and 291xx are reported as "Scheduler Error" ***/ + +/* 2900x: general scheduler error codes */ +extern ndberror_struct AppError29001_ReconfLock; +extern ndberror_struct AppError29002_NoNDBs; + +/* 2902x: blocking NDB operations in worker thread */ +extern ndberror_struct AppError29023_SyncClose; +extern ndberror_struct AppError29024_autogrow; + +/*** Errors 29200 and up are reported as "Memcached Error" ***/ #endif === modified file 'storage/ndb/memcache/include/ndb_pipeline.h' --- a/storage/ndb/memcache/include/ndb_pipeline.h 2012-03-23 23:33:32 +0000 +++ b/storage/ndb/memcache/include/ndb_pipeline.h 2012-04-05 21:00:05 +0000 @@ -26,14 +26,13 @@ #include "workqueue.h" #include "ndb_engine.h" +#include "Scheduler.h" /* This structure is used in both C and C++ code, requiring a small hack: */ #ifdef __cplusplus -/* forward declaration: */ -class Scheduler; -#define C_OR_CPP_SCHEDULER Scheduler +#define CPP_SCHEDULER Scheduler #else -#define C_OR_CPP_SCHEDULER void +#define CPP_SCHEDULER void #endif /* In each pipeline there lives an allocator, which is used for workitems, @@ -83,9 +82,9 @@ typedef struct request_pipeline { unsigned int id; /*! each pipeline has an id */ unsigned int nworkitems; /*! counter used to give each workitem an id */ struct ndb_engine *engine; - pthread_t engine_thread_id; + pthread_t worker_thread_id; allocator_slab_class alligator[ALLIGATOR_ARRAY_SIZE]; /*! an allocator */ - C_OR_CPP_SCHEDULER *scheduler; + CPP_SCHEDULER *scheduler; memory_pool *pool; /*! has the whole lifetime of the pipeline */ } ndb_pipeline; @@ -99,7 +98,7 @@ DECLARE_FUNCTIONS_WITH_C_LINKAGE ndb_pipeline * ndb_pipeline_initialize(struct ndb_engine *); /** create a generic request pipeline */ -ndb_pipeline * get_request_pipeline(int thd_id); +ndb_pipeline * get_request_pipeline(int thd_id, struct ndb_engine *); /** call into a pipeline for its own statistics */ void pipeline_add_stats(ndb_pipeline *, const char *key, ADD_STAT, const void *); @@ -111,7 +110,7 @@ ENGINE_ERROR_CODE pipeline_flush_all(ndb /***** SCHEDULER APIS *****/ /** Global initialization of scheduler, at startup time */ -void * scheduler_initialize(const char *name, int nthreads, int threadnum); +void * scheduler_initialize(ndb_pipeline *, scheduler_options *); /** shutdown a scheduler */ void scheduler_shutdown(ndb_pipeline *); === modified file 'storage/ndb/memcache/include/ndbmemcache_config.in' --- a/storage/ndb/memcache/include/ndbmemcache_config.in 2011-10-14 08:26:28 +0000 +++ b/storage/ndb/memcache/include/ndbmemcache_config.in 2012-03-31 18:56:49 +0000 @@ -41,5 +41,6 @@ #cmakedefine HAVE_FUNC_IN_CXX +#cmakedefine HAVE_HTONLL #endif === modified file 'storage/ndb/memcache/src/ExternalValue.cc' --- a/storage/ndb/memcache/src/ExternalValue.cc 2012-03-23 19:01:07 +0000 +++ b/storage/ndb/memcache/src/ExternalValue.cc 2012-04-05 21:00:05 +0000 @@ -22,6 +22,7 @@ #include #include "workitem.h" +#include "NdbInstance.h" #include "Operation.h" #include "Scheduler.h" #include "status_block.h" === modified file 'storage/ndb/memcache/src/ndb_engine.c' --- a/storage/ndb/memcache/src/ndb_engine.c 2012-03-23 23:33:32 +0000 +++ b/storage/ndb/memcache/src/ndb_engine.c 2012-04-05 21:00:05 +0000 @@ -166,6 +166,7 @@ static ENGINE_ERROR_CODE ndb_initialize( ENGINE_ERROR_CODE return_status; struct ndb_engine *ndb_eng = ndb_handle(handle); struct default_engine *def_eng = default_handle(ndb_eng); + scheduler_options sched_opts; /* Process options for both the ndb engine and the default engine: */ read_cmdline_options(ndb_eng, def_eng, config_str); @@ -212,6 +213,10 @@ static ENGINE_ERROR_CODE ndb_initialize( /* prefetch data dictionary objects */ prefetch_dictionary_objects(); + /* Build the scheduler options structure */ + sched_opts.nthreads = ndb_eng->server_options.nthreads; + sched_opts.max_clients = ndb_eng->server_options.maxconns; + /* Allocate and initailize the pipelines, and their schedulers. This will take some time; each pipeline creates slab and pool allocators, and each scheduler may preallocate a large number of Ndb objects and @@ -224,9 +229,9 @@ static ENGINE_ERROR_CODE ndb_initialize( ndb_eng->pipelines = malloc(nthreads * sizeof(void *)); ndb_eng->schedulers = malloc(nthreads * sizeof(void *)); for(i = 0 ; i < nthreads ; i++) { - ndb_eng->pipelines[i] = get_request_pipeline(i); - ndb_eng->schedulers[i] = - scheduler_initialize(ndb_eng->startup_options.scheduler, nthreads, i); + ndb_eng->pipelines[i] = get_request_pipeline(i, ndb_eng); + ndb_eng->schedulers[i] = scheduler_initialize(ndb_eng->pipelines[i], + & sched_opts); if(ndb_eng->schedulers[i] == 0) { logger->log(LOG_WARNING, NULL, "Illegal scheduler: \"%s\"\n", ndb_eng->startup_options.scheduler); @@ -819,6 +824,9 @@ int fetch_core_settings(struct ndb_engin { .key = "cas_enabled", .datatype = DT_BOOL, .value.dt_bool = &engine->server_options.cas_enabled }, + { .key = "maxconns", + .datatype = DT_SIZE, + .value.dt_size = &engine->server_options.maxconns }, { .key = "num_threads", .datatype = DT_SIZE, .value.dt_size = &engine->server_options.nthreads }, === modified file 'storage/ndb/memcache/src/ndb_engine_errors.cc' --- a/storage/ndb/memcache/src/ndb_engine_errors.cc 2012-03-23 19:01:07 +0000 +++ b/storage/ndb/memcache/src/ndb_engine_errors.cc 2012-04-05 21:37:02 +0000 @@ -20,17 +20,22 @@ #include -ndberror_struct AppError9001_ReconfLock = - { ndberror_st_temporary , ndberror_cl_application , 9001, -1, +ndberror_struct AppError29001_ReconfLock = + { ndberror_st_temporary , ndberror_cl_application , 29001, -1, "Could not obtain configuration read lock", 0 }; -ndberror_struct AppError9002_NoNDBs = - { ndberror_st_temporary , ndberror_cl_application , 9002, -1, +ndberror_struct AppError29002_NoNDBs = + { ndberror_st_temporary , ndberror_cl_application , 29002, -1, "No Ndb Instances in freelist", 0 }; -ndberror_struct AppError9003_SyncClose = - { ndberror_st_temporary , ndberror_cl_application , 9003, -1, +ndberror_struct AppError29023_SyncClose = + { ndberror_st_temporary , ndberror_cl_application , 29023, -1, "Waited for synchronous close of NDB transaction", 0 }; + +ndberror_struct AppError29024_autogrow = + { ndberror_st_temporary , ndberror_cl_application , 29024, -1, + "Out of Ndb instances, growing freelist", 0 + }; === modified file 'storage/ndb/memcache/src/ndb_error_logger.cc' --- a/storage/ndb/memcache/src/ndb_error_logger.cc 2012-03-07 03:57:36 +0000 +++ b/storage/ndb/memcache/src/ndb_error_logger.cc 2012-04-06 01:00:19 +0000 @@ -208,8 +208,10 @@ void ndb_error_logger_stats(ADD_STAT add for(i = 0 ; i < ERROR_HASH_TABLE_SIZE; i++) { for(sym = error_hash_table[i] ; sym != 0 ; sym = sym->next) { - klen = sprintf(key, "NDB_Error_%d", sym->error_code); - vlen = sprintf(val, "%du", sym->count); + klen = sprintf(key, "%s_Error_%d", + (sym->error_code < 29000 ? "NDB" : "Engine"), + sym->error_code); + vlen = sprintf(val, "%lu", (long unsigned int) sym->count); add_stat(key, klen, val, vlen, cookie); } } === modified file 'storage/ndb/memcache/src/ndb_pipeline.cc' --- a/storage/ndb/memcache/src/ndb_pipeline.cc 2012-03-07 01:22:53 +0000 +++ b/storage/ndb/memcache/src/ndb_pipeline.cc 2012-04-03 00:34:18 +0000 @@ -71,7 +71,12 @@ void init_pool_header(allocation_referen /* The public API */ -/* initialize a new pipeline for an NDB engine thread */ +/* Attach a new pipeline to an NDB worker thread. + Some initialization has already occured when the main single-thread startup + called get_request_pipeline(). But this is the first call into a pipeline + from its worker thread. It will initialize the thread's identifier, and + attach the pipeline to its scheduler. +*/ ndb_pipeline * ndb_pipeline_initialize(struct ndb_engine *engine) { bool did_inc; unsigned int id; @@ -85,14 +90,13 @@ ndb_pipeline * ndb_pipeline_initialize(s /* Fetch the partially initialized pipeline */ ndb_pipeline * self = (ndb_pipeline *) engine->pipelines[id]; - + + /* Sanity checks */ assert(self->id == id); + assert(self->engine == engine); - /* Set the pointer back to the engine */ - self->engine = engine; - - /* And the thread id */ - self->engine_thread_id = pthread_self(); + /* Set the pthread id */ + self->worker_thread_id = pthread_self(); /* Create and set a thread identity */ tid = (thread_identifier *) memory_pool_alloc(self->pool, sizeof(thread_identifier)); @@ -108,16 +112,20 @@ ndb_pipeline * ndb_pipeline_initialize(s } -/* Allocate and initialize a generic request pipeline */ -ndb_pipeline * get_request_pipeline(int thd_id) { +/* Allocate and initialize a generic request pipeline. + In unit test code, this can be called with a NULL engine pointer -- + it will still initialize a usable slab allocator and memory pool + which can be tested. +*/ +ndb_pipeline * get_request_pipeline(int thd_id, struct ndb_engine *engine) { /* Allocate the pipeline */ ndb_pipeline *self = (ndb_pipeline *) malloc(sizeof(ndb_pipeline)); /* Initialize */ - self->engine = 0; + self->engine = engine; self->id = thd_id; self->nworkitems = 0; - + /* Say hi to the alligator */ init_allocator(self); @@ -160,27 +168,27 @@ ENGINE_ERROR_CODE pipeline_flush_all(ndb /* The scheduler API */ -void * scheduler_initialize(const char *cf, int nthreads, int athread) { +void * scheduler_initialize(ndb_pipeline *self, scheduler_options *options) { Scheduler *s = 0; - const char *sched_options = 0; + const char *cf = self->engine->startup_options.scheduler; + options->config_string = 0; if(cf == 0 || *cf == 0) { s = new DEFAULT_SCHEDULER; } else if(!strncasecmp(cf, "stockholm", 9)) { s = new Scheduler_stockholm; - sched_options = & cf[9]; + options->config_string = & cf[9]; } else if(!strncasecmp(cf,"S", 1)) { s = new S::SchedulerWorker; - sched_options = & cf[1]; + options->config_string = & cf[1]; } else { return NULL; } - - s->init(athread, nthreads, sched_options); - s->pipeline = 0; + + s->init(self->id, options); return (void *) s; } === modified file 'storage/ndb/memcache/src/ndb_worker.cc' --- a/storage/ndb/memcache/src/ndb_worker.cc 2012-03-23 19:01:07 +0000 +++ b/storage/ndb/memcache/src/ndb_worker.cc 2012-04-05 21:37:02 +0000 @@ -880,7 +880,7 @@ void worker_close(NdbTransaction *tx, wo nwaits_post = ndb->getClientStat(Ndb::WaitExecCompleteCount); if(nwaits_post > nwaits_pre) - log_app_error(& AppError9003_SyncClose); + log_app_error(& AppError29023_SyncClose); if(wqitem->ext_val) delete wqitem->ext_val; === modified file 'storage/ndb/memcache/src/schedulers/S_sched.cc' --- a/storage/ndb/memcache/src/schedulers/S_sched.cc 2012-03-22 19:24:32 +0000 +++ b/storage/ndb/memcache/src/schedulers/S_sched.cc 2012-04-06 01:00:19 +0000 @@ -64,13 +64,14 @@ S::SchedulerGlobal::SchedulerGlobal(Conf } -void S::SchedulerGlobal::init(int _nthreads, const char *_config_string) { +void S::SchedulerGlobal::init(const scheduler_options *sched_opts) { DEBUG_ENTER_METHOD("S::SchedulerGlobal::init"); /* Set member variables */ - nthreads = _nthreads; - config_string = _config_string; + nthreads = sched_opts->nthreads; + config_string = sched_opts->config_string; parse_config_string(nthreads, config_string); + options.max_clients = sched_opts->max_clients; /* Fetch or initialize clusters */ nclusters = conf->nclusters; @@ -104,8 +105,9 @@ void S::SchedulerGlobal::init(int _nthre /* Log message for startup */ logger->log(LOG_WARNING, 0, "Scheduler: starting for %d cluster%s; " - "c%d,f%d,t%d", nclusters, nclusters == 1 ? "" : "s", - options.n_connections, options.force_send, options.send_timer); + "c%d,f%d,g%d,t%d", nclusters, nclusters == 1 ? "" : "s", + options.n_connections, options.force_send, + options.auto_grow, options.send_timer); /* Now Running */ running = true; @@ -171,6 +173,7 @@ void S::SchedulerGlobal::parse_config_st options.n_connections = 0; // 0 = n_connections based on db-stored config options.force_send = 0; // 0 = force send always off options.send_timer = 1; // 1 = 1 ms. timer in send thread + options.auto_grow = 1; // 1 = allow NDB instance pool to grow on demand if(str) { const char *s = str; @@ -188,6 +191,9 @@ void S::SchedulerGlobal::parse_config_st case 'f': options.force_send = value; break; + case 'g': + options.auto_grow = value; + break; case 't': options.send_timer = value; break; @@ -214,6 +220,10 @@ void S::SchedulerGlobal::parse_config_st logger->log(LOG_WARNING, 0, "Invalid scheduler configuration.\n"); assert(options.send_timer >= 1 && options.send_timer <= 10); } + if(options.auto_grow < 0 || options.auto_grow > 1) { + logger->log(LOG_WARNING, 0, "Invalid scheduler configuration.\n"); + assert(options.auto_grow == 0 || options.auto_grow == 1); + } } @@ -249,15 +259,14 @@ void S::SchedulerGlobal::add_stats(const /* SchedulerWorker methods */ void S::SchedulerWorker::init(int my_thread, - int nthreads, - const char * config_string) { + const scheduler_options * options) { /* On the first call in, initialize the SchedulerGlobal. * This will start the send & poll threads for each connection. */ if(my_thread == 0) { sched_generation_number = 1; s_global = new SchedulerGlobal(& get_Configuration()); - s_global->init(nthreads, config_string); + s_global->init(options); } /* Initialize member variables */ @@ -286,7 +295,7 @@ void S::SchedulerWorker::attach_thread(t ENGINE_ERROR_CODE S::SchedulerWorker::schedule(workitem *item) { int c = item->prefix_info.cluster_id; ENGINE_ERROR_CODE response_code; - NdbInstance *inst; + NdbInstance *inst = 0; S::WorkerConnection *wc; const KeyPrefix *pfx; @@ -299,29 +308,41 @@ ENGINE_ERROR_CODE S::SchedulerWorker::sc pthread_rwlock_unlock(& reconf_lock); } else { - log_app_error(& AppError9001_ReconfLock); + log_app_error(& AppError29001_ReconfLock); return ENGINE_TMPFAIL; } /* READ LOCK RELEASED */ item->base.nsuffix = item->base.nkey - pfx->prefix_len; if(item->base.nsuffix == 0) return ENGINE_EINVAL; // key too short - - if(wc && wc->freelist) { + + if(wc == 0) return ENGINE_FAILED; + + if(wc->freelist) { /* Get the next NDB from the freelist. */ inst = wc->freelist; wc->freelist = inst->next; } - else { - /* No more free NDBs. - Eventually Scheduler::io_completed() will run _in this thread_ and return - an NDB to the freelist. But no other thread can free one, so - all we can do is return an error. - (Or, alternately, the scheduler may be shutting down.) - */ - log_app_error(& AppError9002_NoNDBs); - return ENGINE_TMPFAIL; + else { /* No free NDBs. */ + if(wc->sendqueue->is_aborted()) { + return ENGINE_TMPFAIL; + } + else { /* Try to make an NdbInstance on the fly */ + inst = wc->newNdbInstance(); + if(inst) { + log_app_error(& AppError29024_autogrow); + } + else { + /* We have hit a hard maximum. Eventually Scheduler::io_completed() + will run _in this thread_ and return an NDB to the freelist. + But no other thread can free one, so here we return an error. + */ + log_app_error(& AppError29002_NoNDBs); + return ENGINE_TMPFAIL; + } + } } + assert(inst); inst->link_workitem(item); // Fetch the query plan for this prefix. @@ -520,6 +541,18 @@ void S::Cluster::add_stats(const char *s /* WorkerConnection methods */ + +NdbInstance * S::WorkerConnection::newNdbInstance() { + NdbInstance *inst = 0; + if(instances.current < instances.max) { + inst = new NdbInstance(conn->conn, 2); + instances.current++; + inst->id = ((id.thd + 1) * 10000) + instances.current; + } + return inst; +} + + S::WorkerConnection::WorkerConnection(SchedulerGlobal *global, int thd_id, int cluster_id) { S::Cluster *cl = global->clusters[cluster_id]; @@ -536,21 +569,25 @@ S::WorkerConnection::WorkerConnection(Sc plan_set = new ConnQueryPlanSet(conn->conn, conf->nprefixes); plan_set->buildSetForConfiguration(conf, cluster_id); + /* How many NDB instances to start initially */ + instances.initial = conn->instances.initial / conn->n_workers; + + /* Maximum size of send queue, and upper bound on NDB instances */ + instances.max = conn->instances.max / conn->n_workers; + /* Build the freelist */ freelist = 0; - int my_ndb_inst = conn->nInst / conn->n_workers; - for(int j = 0 ; j < my_ndb_inst ; j++ ) { - NdbInstance *inst = new NdbInstance(conn->conn, 2); - inst->id = ((id.thd + 1) * 10000) + j + 1; + for(instances.current = 0; instances.current < instances.initial; ) { + NdbInstance *inst = newNdbInstance(); inst->next = freelist; freelist = inst; } DEBUG_PRINT("Cluster %d, connection %d (node %d), worker %d: %d NDBs.", - id.cluster, id.conn, id.node, id.thd, my_ndb_inst); + id.cluster, id.conn, id.node, id.thd, instances.current); /* Initialize the sendqueue */ - sendqueue = new Queue(my_ndb_inst); + sendqueue = new Queue(instances.max); /* Hoard a transaction (an API connect record) for each Ndb object. This * first call to startTransaction() will send TC_SEIZEREQ and wait for a @@ -560,7 +597,7 @@ S::WorkerConnection::WorkerConnection(Sc QueryPlan *plan; const KeyPrefix *prefix = conf->getNextPrefixForCluster(id.cluster, NULL); if(prefix) { - NdbTransaction ** txlist = new NdbTransaction * [my_ndb_inst]; + NdbTransaction ** txlist = new NdbTransaction * [instances.current]; int i = 0; // Open them all. @@ -573,7 +610,7 @@ S::WorkerConnection::WorkerConnection(Sc } // Close them all. - for(i = 0 ; i < my_ndb_inst ; i++) { + for(i = 0 ; i < instances.current ; i++) { txlist[i]->close(); } @@ -642,17 +679,29 @@ S::Connection::Connection(S::Cluster & _ n_workers = global->options.n_worker_threads / cluster.nconnections; if(n_total_workers % cluster.nconnections > id) n_workers += 1; - /* How many NDB objects are needed? */ - /* Note that this is used to configure hard limits on the size of the - * waitgroup, the sentqueue, and the reschedulequeue -- and it will not be + /* How many NDB objects are needed for the desired performance? */ + double total_ndb_objects = conf->figureInFlightTransactions(cluster.cluster_id); + instances.initial = (int) (total_ndb_objects / cluster.nconnections); + while(instances.initial % n_workers) instances.initial++; // round up + + /* The maximum number of NDB objects. + * This is used to configure hard limits on the size of the waitgroup, + * the sentqueue, and the reschedulequeue -- and it will not be * possible to increase those limits during online reconfig. */ - double total_ndb_objects = conf->figureInFlightTransactions(cluster.cluster_id); - nInst = (int) (total_ndb_objects / cluster.nconnections); - while(nInst % n_workers) nInst++; // round up - + instances.max = instances.initial; + // allow the pool to grow on demand? + if(global->options.auto_grow) + instances.max = (int) (instances.max * 1.6); + // max_clients imposes a hard upper limit + if(instances.max > (global->options.max_clients / cluster.nconnections)) + instances.max = global->options.max_clients / cluster.nconnections; + // instances.initial might also be subject to the max_clients limit + if(instances.initial > instances.max) + instances.initial = instances.max; + /* Get a multi-wait Poll Group */ - pollgroup = conn->create_ndb_wait_group(nInst); + pollgroup = conn->create_ndb_wait_group(instances.max); /* Initialize the statistics */ stats.sent_operations = 0; @@ -665,8 +714,8 @@ S::Connection::Connection(S::Cluster & _ sem.counter = 0; /* Initialize the queues for sent and resceduled items */ - sentqueue = new Queue(nInst); - reschedulequeue = new Queue(nInst); + sentqueue = new Queue(instances.max); + reschedulequeue = new Queue(instances.max); } @@ -726,6 +775,14 @@ void S::Connection::add_stats(const char klen = sprintf(key, "cl%d.conn%d.timeout_races", cluster.cluster_id, id); vlen = sprintf(val, "%llu", stats.timeout_races); add_stat(key, klen, val, vlen, cookie); + + klen = sprintf(key, "cl%d.conn%d.instances.initial", cluster.cluster_id, id); + vlen = sprintf(val, "%d", instances.initial); + add_stat(key, klen, val, vlen, cookie); + + klen = sprintf(key, "cl%d.conn%d.instances.max", cluster.cluster_id, id); + vlen = sprintf(val, "%d", instances.max); + add_stat(key, klen, val, vlen, cookie); } === modified file 'storage/ndb/memcache/src/schedulers/S_sched.h' --- a/storage/ndb/memcache/src/schedulers/S_sched.h 2012-03-07 01:22:53 +0000 +++ b/storage/ndb/memcache/src/schedulers/S_sched.h 2012-04-06 00:12:54 +0000 @@ -61,7 +61,7 @@ class S::SchedulerGlobal { public: SchedulerGlobal(Configuration *); ~SchedulerGlobal() {}; - void init(int threads, const char *config_string); + void init(const scheduler_options *options); void add_stats(const char *, ADD_STAT, const void *); void reconfigure(Configuration *); void shutdown(); @@ -82,6 +82,8 @@ public: int n_connections; /** preferred number of NDB cluster connections */ int force_send; /** how to use NDB force-send */ int send_timer; /** milliseconds to set for adaptive send timer */ + int auto_grow; /** whether to allow NDB instance pool to grow */ + int max_clients; /** memcached max allowed connections */ } options; private: @@ -99,7 +101,7 @@ class S::SchedulerWorker : public Schedu public: SchedulerWorker() {}; ~SchedulerWorker() {}; - void init(int threadnum, int nthreads, const char *config_string); + void init(int threadnum, const scheduler_options * sched_opts); void attach_thread(thread_identifier *); ENGINE_ERROR_CODE schedule(workitem *); void yield(workitem *) const {}; @@ -111,6 +113,7 @@ public: private: int id; + ndb_pipeline *pipeline; SchedulerGlobal * m_global; }; @@ -159,9 +162,12 @@ private: Queue * reschedulequeue; int id; int node_id; - int nInst; - int n_total_workers; - int n_workers; + int n_total_workers; /* same as SchedulerGlobal::options.n_worker_threads */ + int n_workers; /* number of workers for this connection */ + struct { + int initial; /* start with this many NDB instances */ + int max; /* scale up to this many */ + } instances; pthread_t send_thread_id; pthread_t poll_thread_id; struct { @@ -187,6 +193,7 @@ public: ~WorkerConnection(); void shutdown(); void reconfigure(Configuration *); + NdbInstance * newNdbInstance(); struct { int thd : 8; @@ -194,6 +201,11 @@ public: int conn : 8; unsigned int node : 8; } id; + struct { + int initial; + int current; + int max; + } instances; S::Connection *conn; ConnQueryPlanSet *plan_set, *old_plan_set; NdbInstance *freelist; === modified file 'storage/ndb/memcache/src/schedulers/Stockholm.cc' --- a/storage/ndb/memcache/src/schedulers/Stockholm.cc 2012-03-07 01:22:53 +0000 +++ b/storage/ndb/memcache/src/schedulers/Stockholm.cc 2012-04-03 00:34:18 +0000 @@ -46,14 +46,15 @@ extern "C" { } -void Scheduler_stockholm::init(int my_thread, int nthreads, const char *config_string) { +void Scheduler_stockholm::init(int my_thread, + const scheduler_options *options) { const Configuration & conf = get_Configuration(); /* How many NDB instances are needed per cluster? */ for(unsigned int c = 0 ; c < conf.nclusters ; c++) { ClusterConnectionPool *pool = conf.getConnectionPoolById(c); double total_ndb_objects = conf.figureInFlightTransactions(c); - cluster[c].nInst = (int) total_ndb_objects / nthreads; + cluster[c].nInst = (int) total_ndb_objects / options->nthreads; DEBUG_PRINT("cluster %d: %d TPS @ %d usec RTT ==> %d NDB instances.", c, conf.max_tps, pool->usec_rtt, cluster[c].nInst); } === modified file 'storage/ndb/memcache/src/schedulers/Stockholm.h' --- a/storage/ndb/memcache/src/schedulers/Stockholm.h 2012-03-07 01:22:53 +0000 +++ b/storage/ndb/memcache/src/schedulers/Stockholm.h 2012-04-03 00:34:18 +0000 @@ -44,7 +44,7 @@ class Scheduler_stockholm : public Sched public: Scheduler_stockholm() {}; ~Scheduler_stockholm() {}; - void init(int threadnum, int nthreads, const char *config_string); + void init(int threadnum, const scheduler_options *options); void attach_thread(thread_identifier *); ENGINE_ERROR_CODE schedule(workitem *); void yield(workitem *) const; // inlined @@ -56,6 +56,7 @@ public: bool global_reconfigure(Configuration *) { return false; } ; private: + ndb_pipeline *pipeline; struct { struct workqueue *queue; struct sched_stats_stockholm { === modified file 'storage/ndb/memcache/unit/alloc.cc' --- a/storage/ndb/memcache/unit/alloc.cc 2011-12-18 23:26:44 +0000 +++ b/storage/ndb/memcache/unit/alloc.cc 2012-04-03 00:34:18 +0000 @@ -27,14 +27,16 @@ #include "all_tests.h" +#define TEST_ALLOC_BLOCKS 34 + int run_allocator_test(QueryPlan *, Ndb *, int v) { - struct request_pipeline *p = get_request_pipeline(0); + struct request_pipeline *p = get_request_pipeline(0, NULL); memory_pool *p1 = pipeline_create_memory_pool(p); int sz = 13; uint tot = 0; void *v1, *v2; - for(int i = 0 ; i < 25 ; i++) { + for(int i = 0 ; i < TEST_ALLOC_BLOCKS ; i++) { v1 = memory_pool_alloc(p1, sz); tot += sz; v2 = memory_pool_alloc(p1, sz + 1); tot += sz + 1; sz = (int) (sz * 1.25); === modified file 'storage/ndb/src/ndbapi/NdbQueryBuilder.cpp' --- a/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp 2012-03-30 12:40:48 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp 2012-04-11 10:34:58 +0000 @@ -702,24 +702,7 @@ NdbQueryOperationDef::getIndex() const NdbQueryBuilder* NdbQueryBuilder::create() { NdbQueryBuilderImpl* const impl = new NdbQueryBuilderImpl(); - if (likely (impl != NULL)) - { - if (likely(impl->getNdbError().code == 0)) - { - return &impl->m_interface; - } - else - { - // Probably failed to create Vector instances. - assert(impl->getNdbError().code == Err_MemoryAlloc); - delete impl; - return NULL; - } - } - else - { - return NULL; - } + return (likely(impl!=NULL)) ? &impl->m_interface : NULL; } void NdbQueryBuilder::destroy() @@ -1116,17 +1099,11 @@ NdbQueryBuilder::prepare() NdbQueryBuilderImpl::NdbQueryBuilderImpl() : m_interface(*this), m_error(), - m_operations(), - m_operands(), + m_operations(0), + m_operands(0), m_paramCnt(0), m_hasError(false) -{ - if (errno == ENOMEM) - { - // ENOMEM probably comes from Vector(). - setErrorCode(Err_MemoryAlloc); - } -} +{} NdbQueryBuilderImpl::~NdbQueryBuilderImpl() { @@ -1242,12 +1219,12 @@ NdbQueryDefImpl(const Vector& operands, int& error) : m_interface(*this), - m_operations(operations), - m_operands(operands) + m_operations(0), + m_operands(0) { - if (errno == ENOMEM) + if (m_operations.assign(operations) || m_operands.assign(operands)) { - // Failed to allocate memory for m_operations or m_operands. + // Failed to allocate memory in Vector::assign(). error = Err_MemoryAlloc; return; } @@ -1909,16 +1886,10 @@ NdbQueryOperationDefImpl::NdbQueryOperat m_opNo(opNo), m_internalOpNo(internalOpNo), m_options(options), m_parent(NULL), - m_children(), - m_params(), - m_spjProjection() + m_children(0), + m_params(0), + m_spjProjection(0) { - if (unlikely(errno == ENOMEM)) - { - // Heap allocation in Vector() must have failed. - error = Err_MemoryAlloc; - return; - } if (unlikely(m_internalOpNo >= NDB_SPJ_MAX_TREE_NODES)) { error = QRY_DEFINITION_TOO_LARGE; === modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp' --- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2012-03-30 12:40:48 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2012-04-11 10:34:58 +0000 @@ -3788,7 +3788,7 @@ NdbQueryOperationImpl::NdbQueryOperation m_queryImpl(queryImpl), m_operationDef(def), m_parent(NULL), - m_children(def.getNoOfChildOperations()), + m_children(0), m_maxBatchRows(0), // >0: User specified prefered value, ==0: Use default CFG values m_params(), m_resultBuffer(NULL), @@ -3805,9 +3805,9 @@ NdbQueryOperationImpl::NdbQueryOperation ? Parallelism_max : Parallelism_adaptive), m_rowSize(0xffffffff) { - if (errno == ENOMEM) + if (m_children.expand(def.getNoOfChildOperations())) { - // Memory allocation in Vector() (for m_children) assumed to have failed. + // Memory allocation during Vector::expand() failed. queryImpl.setErrorCode(Err_MemoryAlloc); return; } === modified file 'storage/ndb/test/CMakeLists.txt' --- a/storage/ndb/test/CMakeLists.txt 2011-07-05 12:46:07 +0000 +++ b/storage/ndb/test/CMakeLists.txt 2012-04-11 10:34:58 +0000 @@ -15,8 +15,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADD_SUBDIRECTORY(src) -IF(WITH_NDB_TEST) +#IF(WITH_NDB_TEST) ADD_SUBDIRECTORY(tools) ADD_SUBDIRECTORY(ndbapi) ADD_SUBDIRECTORY(run-test) -ENDIF(WITH_NDB_TEST) +#ENDIF(WITH_NDB_TEST) No bundle (reason: useless for push emails).