diff options
author | unknown <monty@donna.mysql.com> | 2001-02-17 14:19:19 +0200 |
---|---|---|
committer | unknown <monty@donna.mysql.com> | 2001-02-17 14:19:19 +0200 |
commit | 2662b59306ef0cd495fa6e2edf7129e58a11393a (patch) | |
tree | bfe39951a73e906579ab819bf5198ad8f3a64a36 /innobase/com | |
parent | 66de55a56bdcf2f7a9c0c4f8e19b3e761475e202 (diff) | |
download | mariadb-git-2662b59306ef0cd495fa6e2edf7129e58a11393a.tar.gz |
Added Innobase to source distribution
Docs/manual.texi:
Added Innobase documentation
configure.in:
Incremented version
include/my_base.h:
Added option for Innobase
myisam/mi_check.c:
cleanup
mysql-test/t/bdb.test:
cleanup
mysql-test/t/innobase.test:
Extended with new tests from bdb.test
mysql-test/t/merge.test:
Added test of SHOW create
mysys/my_init.c:
Fix for UNIXWARE 7
scripts/mysql_install_db.sh:
Always write how to start mysqld
scripts/safe_mysqld.sh:
Fixed type
sql/ha_innobase.cc:
Update to new version
sql/ha_innobase.h:
Update to new version
sql/handler.h:
Added 'update_table_comment()' and 'append_create_info()'
sql/sql_delete.cc:
Fixes for Innobase
sql/sql_select.cc:
Fixes for Innobase
sql/sql_show.cc:
Append create information (for MERGE tables)
sql/sql_update.cc:
Fixes for Innobase
Diffstat (limited to 'innobase/com')
-rw-r--r-- | innobase/com/Makefile.am | 24 | ||||
-rw-r--r-- | innobase/com/com0com.c | 345 | ||||
-rw-r--r-- | innobase/com/com0shm.c | 1159 | ||||
-rw-r--r-- | innobase/com/makefilewin | 12 | ||||
-rw-r--r-- | innobase/com/ts/makefile | 19 | ||||
-rw-r--r-- | innobase/com/ts/tscli.c | 96 | ||||
-rw-r--r-- | innobase/com/ts/tscom.c | 94 |
7 files changed, 1749 insertions, 0 deletions
diff --git a/innobase/com/Makefile.am b/innobase/com/Makefile.am new file mode 100644 index 00000000000..27ae396bc6e --- /dev/null +++ b/innobase/com/Makefile.am @@ -0,0 +1,24 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# & Innobase Oy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +include ../include/Makefile.i + +libs_LIBRARIES = libcom.a + +libcom_a_SOURCES = com0com.c com0shm.c + +EXTRA_PROGRAMS = diff --git a/innobase/com/com0com.c b/innobase/com/com0com.c new file mode 100644 index 00000000000..94585d9f269 --- /dev/null +++ b/innobase/com/com0com.c @@ -0,0 +1,345 @@ +/****************************************************** +The communication primitives + +(c) 1995 Innobase Oy + +Created 9/23/1995 Heikki Tuuri +*******************************************************/ + +#include "com0com.h" +#ifdef UNIV_NONINL +#include "com0com.ic" +#endif + +#include "mem0mem.h" +#include "com0shm.h" + +/* + IMPLEMENTATION OF COMMUNICATION PRIMITIVES + ========================================== + +The primitives provide a uniform function interface for +use in communication. The primitives have been modeled +after the Windows Sockets interface. Below this uniform +API, the precise methods of communication, for example, +shared memory or Berkeley sockets, can be implemented +as subroutines. +*/ + +struct com_endpoint_struct{ + ulint type; /* endpoint type */ + void* par; /* type-specific data structures */ + ibool bound; /* TRUE if the endpoint has been + bound to an address */ +}; + +/************************************************************************* +Accessor functions for an endpoint */ +UNIV_INLINE +ulint +com_endpoint_get_type( +/*==================*/ + com_endpoint_t* ep) +{ + ut_ad(ep); + return(ep->type); +} + +UNIV_INLINE +void +com_endpoint_set_type( +/*==================*/ + com_endpoint_t* ep, + ulint type) +{ + ut_ad(ep); + ut_ad(type == COM_SHM); + + ep->type = type; +} + +UNIV_INLINE +void* +com_endpoint_get_par( +/*=================*/ + com_endpoint_t* ep) +{ + ut_ad(ep); + return(ep->par); +} + +UNIV_INLINE +void +com_endpoint_set_par( +/*=================*/ + com_endpoint_t* ep, + void* par) +{ + ut_ad(ep); + ut_ad(par); + + ep->par = par; +} + +UNIV_INLINE +ibool +com_endpoint_get_bound( +/*===================*/ + com_endpoint_t* ep) +{ + ut_ad(ep); + return(ep->bound); +} + +UNIV_INLINE +void +com_endpoint_set_bound( +/*===================*/ + com_endpoint_t* ep, + ibool bound) +{ + ut_ad(ep); + + ep->bound = bound; +} + + +/************************************************************************* +Creates a communications endpoint. */ + +com_endpoint_t* +com_endpoint_create( +/*================*/ + /* out, own: communications endpoint, NULL if + did not succeed */ + ulint type) /* in: communication type of endpoint: + only COM_SHM supported */ +{ + com_endpoint_t* ep; + void* par; + + ep = mem_alloc(sizeof(com_endpoint_t)); + + com_endpoint_set_type(ep, type); + com_endpoint_set_bound(ep, FALSE); + + if (type == COM_SHM) { + par = com_shm_endpoint_create(); + com_endpoint_set_par(ep, par); + } else { + par = NULL; + ut_error; + } + + if (par != NULL) { + return(ep); + } else { + mem_free(ep); + return(NULL); + } +} + +/************************************************************************* +Frees a communications endpoint. */ + +ulint +com_endpoint_free( +/*==============*/ + /* out: O if succeed, else error number */ + com_endpoint_t* ep) /* in, own: communications endpoint */ +{ + ulint type; + ulint ret; + void* par; + + type = com_endpoint_get_type(ep); + par = com_endpoint_get_par(ep); + + if (type == COM_SHM) { + ret = com_shm_endpoint_free((com_shm_endpoint_t*)par); + } else { + ret = 0; + ut_error; + } + + if (ret) { + return(ret); + } else { + mem_free(ep); + return(0); + } +} + +/************************************************************************* +Sets an option, like the maximum datagram size for an endpoint. +The options may vary depending on the endpoint type. */ + +ulint +com_endpoint_set_option( +/*====================*/ + /* out: 0 if succeed, else error number */ + com_endpoint_t* ep, /* in: endpoint */ + ulint optno, /* in: option number, only + COM_OPT_MAX_DGRAM_SIZE currently supported */ + byte* optval, /* in: pointer to a buffer containing the + option value to set */ + ulint optlen) /* in: option value buffer length */ +{ + ulint type; + ulint ret; + void* par; + + type = com_endpoint_get_type(ep); + par = com_endpoint_get_par(ep); + + if (type == COM_SHM) { + ret = com_shm_endpoint_set_option((com_shm_endpoint_t*)par, + optno, optval, optlen); + } else { + ret = 0; + ut_error; + } + + return(ret); +} + +/************************************************************************* +Binds a communications endpoint to the specified address. */ + +ulint +com_bind( +/*=====*/ + /* out: 0 if succeed, else error number */ + com_endpoint_t* ep, /* in: communications endpoint */ + char* name, /* in: address name */ + ulint len) /* in: name length */ +{ + ulint type; + ulint ret; + void* par; + + ut_ad(len <= COM_MAX_ADDR_LEN); + + if (com_endpoint_get_bound(ep)) { + return(COM_ERR_ALREADY_BOUND); + } + + type = com_endpoint_get_type(ep); + par = com_endpoint_get_par(ep); + + if (type == COM_SHM) { + ret = com_shm_bind((com_shm_endpoint_t*)par, name, len); + } else { + ret = 0; + ut_error; + } + + if (ret == 0) { + com_endpoint_set_bound(ep, TRUE); + } + + return(ret); +} + +/************************************************************************* +Waits for a datagram to arrive at an endpoint. */ + +ulint +com_recvfrom( +/*=========*/ + /* out: 0 if succeed, else error number */ + com_endpoint_t* ep, /* in: communications endpoint */ + byte* buf, /* out: datagram buffer; the buffer is + supplied by the caller */ + ulint buf_len,/* in: datagram buffer length */ + ulint* len, /* out: datagram length */ + char* from, /* out: address name buffer; the buffer is + supplied by the caller */ + ulint from_len,/* in: address name buffer length */ + ulint* addr_len)/* out: address name length */ +{ + ulint type; + ulint ret; + void* par; + + if (!com_endpoint_get_bound(ep)) { + + return(COM_ERR_NOT_BOUND); + } + + type = com_endpoint_get_type(ep); + par = com_endpoint_get_par(ep); + + if (type == COM_SHM) { + ret = com_shm_recvfrom((com_shm_endpoint_t*)par, + buf, buf_len, len, from, from_len, + addr_len); + } else { + ret = 0; + + ut_error; + } + + return(ret); +} + +/************************************************************************* +Sends a datagram to the specified destination. */ + +ulint +com_sendto( +/*=======*/ + /* out: 0 if succeed, else error number */ + com_endpoint_t* ep, /* in: communications endpoint */ + byte* buf, /* in: datagram buffer */ + ulint len, /* in: datagram length */ + char* to, /* in: address name buffer */ + ulint tolen) /* in: address name length */ +{ + ulint type; + ulint ret; + void* par; + + if (!com_endpoint_get_bound(ep)) { + return(COM_ERR_NOT_BOUND); + } + + type = com_endpoint_get_type(ep); + par = com_endpoint_get_par(ep); + + if (type == COM_SHM) { + ret = com_shm_sendto((com_shm_endpoint_t*)par, buf, len, + to, tolen); + } else { + ret = 0; + ut_error; + } + + return(ret); +} + +/************************************************************************* +Gets the maximum datagram size for an endpoint. */ + +ulint +com_endpoint_get_max_size( +/*======================*/ + /* out: maximum size */ + com_endpoint_t* ep) /* in: endpoint */ +{ + ulint type; + ulint ret; + void* par; + + type = com_endpoint_get_type(ep); + par = com_endpoint_get_par(ep); + + if (type == COM_SHM) { + ret = com_shm_endpoint_get_size((com_shm_endpoint_t*)par); + } else { + ret = 0; + ut_error; + } + + return(ret); +} diff --git a/innobase/com/com0shm.c b/innobase/com/com0shm.c new file mode 100644 index 00000000000..630241ff2f1 --- /dev/null +++ b/innobase/com/com0shm.c @@ -0,0 +1,1159 @@ +/****************************************************** +The communication through shared memory + +(c) 1995 Innobase Oy + +Created 9/25/1995 Heikki Tuuri +*******************************************************/ + +#include "com0shm.h" +#ifdef UNIV_NONINL +#include "com0shm.ic" +#endif + +#include "mem0mem.h" +#include "ut0mem.h" +#include "com0com.h" +#include "os0shm.h" +#include "sync0sync.h" +#include "sync0ipm.h" +#include "hash0hash.h" + +/* + IMPLEMENTATION OF COMMUNICATION PRIMITIVES + ========================================== + +When bind is called for an endpoint, a shared memory area of +a size specified by com_shm_set_option is created with the +name of the address given concatenated to "_IBSHM". +Also a mutex is created for controlling the access to the +shared memory area. The name of the mutex is address + "_IBSHM_MTX". +An event with name address + "_IBSHM_EV_NE" is created. This event +is in signaled state when the shared memory area is not empty, i.e., +there is a datagram to read. An event address + "_IBSHM_EV_EM" +is signaled, when the area is empty, i.e., a datagram can be +written to it. + +The shared memory area consists of an info struct +at the beginning, containing fields telling: +if the area is valid, i.e., is anybody going to +read it, whether it currently contains a datagram, the +length of the address from which the datagram was received, +the length of the datagram, and the maximum allowed length of +a datagram. +After the info struct, there is a string of bytes +containing the sender address and the data +of the datagram. +*/ + +/* The following is set TRUE when the first endpoint is created. */ + +ibool com_shm_initialized = FALSE; + +/* When a datagram is sent, the shared memory area +corresponding to the destination address is mapped +to the address space of this (sender) process. +We preserve it and keep the relevant info in the +following list. We can save a lot of CPU time +if the destination can be found on the list. The list is +protected by the mutex below. */ + +mutex_t com_shm_destination_mutex; +hash_table_t* com_shm_destination_cache; +UT_LIST_BASE_NODE_T(com_shm_endpoint_t) + com_shm_destination_list; + +/* The number of successfully bound endpoints in this process. When this +number drops to 0, the destination cache is freed. This variable is protected +by com_shm_destination_mutex above. */ + +ulint com_shm_bind_count = 0; + +/* The performance of communication in NT depends on how +many times a system call is made (excluding os_thread_yield, +as that is the fastest way to switch thread). +The following variable counts such events. */ + +ulint com_shm_system_call_count = 0; + +/* The info struct at the beginning of a shared memory area */ + +typedef struct com_shm_info_struct com_shm_info_t; + +/* An area of shared memory consists of an info struct followed +by a string of bytes. */ + +typedef com_shm_info_t com_shm_t; + +struct com_shm_endpoint_struct{ + ibool owns_shm; /* This is true if the shared memory + area is owned by this endpoint structure + (it may also be opened for this endpoint, + not created, in which case does not own it) */ + char* addr; /* pointer to address the endpoint is bound + to, NULL if not bound */ + ulint addr_len; /* address length */ + ulint size; /* maximum allowed datagram size, initialized + to 0 at creation */ + os_shm_t shm; /* operating system handle of the shared + memory area */ + com_shm_t* map; /* pointer to the start address of the shared + memory area */ + os_event_t not_empty; /* this is in the signaled state if + the area currently may contain a datagram; + NOTE: automatic event */ + os_event_t empty; /* this is in the signaled state if the area + currently may be empty; NOTE: automatic event */ + ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex + protecting the shared memory */ + UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct + is inserted into a list, this contains + pointers to next and prev */ + com_shm_endpoint_t* addr_hash; + /* hash table link */ +}; + +struct com_shm_info_struct{ + ulint valid; /* This is COM_SHM_VALID if the creator + of the shared memory area has it still + mapped to its address space. Otherwise, + we may conclude that the datagram cannot + be delivered. */ + ibool not_empty; /* TRUE if the area currently contains + a datagram */ + ulint empty_waiters; /* Count of (writer) threads which are + waiting for the empty-event */ + ulint max_len;/* maximum allowed length for a datagram */ + ulint addr_len;/* address length for the sender address */ + ulint data_len;/* datagram length */ + ip_mutex_t ip_mutex;/* fast interprocess mutex protecting + the shared memory area */ +}; + +#define COM_SHM_VALID 76640 + +/************************************************************************* +Accessor functions for a shared memory endpoint */ + +UNIV_INLINE +ibool +com_shm_endpoint_get_owns_shm( +/*==========================*/ + com_shm_endpoint_t* ep) +{ + ut_ad(ep); + return(ep->owns_shm); +} + +UNIV_INLINE +void +com_shm_endpoint_set_owns_shm( +/*==========================*/ + com_shm_endpoint_t* ep, + ibool flag) +{ + ut_ad(ep); + + ep->owns_shm = flag; +} + +UNIV_INLINE +char* +com_shm_endpoint_get_addr( +/*======================*/ + com_shm_endpoint_t* ep) +{ + ut_ad(ep); + return(ep->addr); +} + +UNIV_INLINE +void +com_shm_endpoint_set_addr( +/*======================*/ + com_shm_endpoint_t* ep, + char* addr) +{ + ut_ad(ep); + + ep->addr = addr; +} + +UNIV_INLINE +ulint +com_shm_endpoint_get_addr_len( +/*==========================*/ + com_shm_endpoint_t* ep) +{ + return(ep->addr_len); +} + +UNIV_INLINE +void +com_shm_endpoint_set_addr_len( +/*==========================*/ + com_shm_endpoint_t* ep, + ulint len) +{ + ut_ad(ep); + ut_ad(len > 0); + + ep->addr_len = len; +} + +ulint +com_shm_endpoint_get_size( +/*======================*/ + com_shm_endpoint_t* ep) +{ + return(ep->size); +} + +UNIV_INLINE +void +com_shm_endpoint_set_size( +/*======================*/ + com_shm_endpoint_t* ep, + ulint size) +{ + ut_ad(ep); + + ep->size = size; +} + +UNIV_INLINE +os_shm_t +com_shm_endpoint_get_shm( +/*=====================*/ + com_shm_endpoint_t* ep) +{ + return(ep->shm); +} + +UNIV_INLINE +void +com_shm_endpoint_set_shm( +/*=====================*/ + com_shm_endpoint_t* ep, + os_shm_t shm) +{ + ut_ad(ep); + ut_ad(shm); + + ep->shm = shm; +} + +UNIV_INLINE +com_shm_t* +com_shm_endpoint_get_map( +/*=====================*/ + com_shm_endpoint_t* ep) +{ + return(ep->map); +} + +UNIV_INLINE +void +com_shm_endpoint_set_map( +/*=====================*/ + com_shm_endpoint_t* ep, + com_shm_t* map) +{ + ut_ad(ep); + ut_ad(map); + + ep->map = map; +} + +UNIV_INLINE +os_event_t +com_shm_endpoint_get_empty( +/*=======================*/ + com_shm_endpoint_t* ep) +{ + return(ep->empty); +} + +UNIV_INLINE +void +com_shm_endpoint_set_empty( +/*=======================*/ + com_shm_endpoint_t* ep, + os_event_t event) +{ + ut_ad(ep); + ut_ad(event); + + ep->empty = event; +} + +UNIV_INLINE +os_event_t +com_shm_endpoint_get_not_empty( +/*===========================*/ + com_shm_endpoint_t* ep) +{ + return(ep->not_empty); +} + +UNIV_INLINE +void +com_shm_endpoint_set_not_empty( +/*===========================*/ + com_shm_endpoint_t* ep, + os_event_t event) +{ + ut_ad(ep); + ut_ad(event); + + ep->not_empty = event; +} + +/************************************************************************ +Accessor functions for the shared memory area info struct. */ +UNIV_INLINE +ulint +com_shm_get_valid( +/*==============*/ + com_shm_info_t* info) +{ + return(info->valid); +} + +UNIV_INLINE +void +com_shm_set_valid( +/*==============*/ + com_shm_info_t* info, + ulint flag) +{ + ut_ad(info); + + info->valid = flag; +} + +UNIV_INLINE +ibool +com_shm_get_not_empty( +/*==================*/ + com_shm_info_t* info) +{ + return(info->not_empty); +} + +UNIV_INLINE +void +com_shm_set_not_empty( +/*==================*/ + com_shm_info_t* info, + ibool flag) +{ + ut_ad(info); + + info->not_empty = flag; +} + +UNIV_INLINE +ulint +com_shm_get_empty_waiters( +/*======================*/ + com_shm_info_t* info) +{ + ut_ad(info->empty_waiters < 1000); + + return(info->empty_waiters); +} + +UNIV_INLINE +void +com_shm_set_empty_waiters( +/*======================*/ + com_shm_info_t* info, + ulint count) +{ + ut_ad(info); + ut_ad(count < 1000); + + info->empty_waiters = count; +} + +UNIV_INLINE +ulint +com_shm_get_max_len( +/*================*/ + com_shm_info_t* info) +{ + return(info->max_len); +} + +UNIV_INLINE +void +com_shm_set_max_len( +/*================*/ + com_shm_info_t* info, + ulint len) +{ + ut_ad(info); + ut_ad(len > 0); + + info->max_len = len; +} + +UNIV_INLINE +ulint +com_shm_get_addr_len( +/*=================*/ + com_shm_info_t* info) +{ + return(info->addr_len); +} + +UNIV_INLINE +void +com_shm_set_addr_len( +/*=================*/ + com_shm_info_t* info, + ulint len) +{ + ut_ad(info); + ut_ad(len > 0); + + info->addr_len = len; +} + +UNIV_INLINE +ulint +com_shm_get_data_len( +/*=================*/ + com_shm_info_t* info) +{ + return(info->data_len); +} + +UNIV_INLINE +void +com_shm_set_data_len( +/*=================*/ + com_shm_info_t* info, + ulint len) +{ + ut_ad(info); + ut_ad(len > 0); + + info->data_len = len; +} + +UNIV_INLINE +ip_mutex_t* +com_shm_get_ip_mutex( +/*=================*/ + com_shm_info_t* info) +{ + return(&(info->ip_mutex)); +} + +/************************************************************************* +Accessor functions for the address and datagram fields inside a +shared memory area. */ + +UNIV_INLINE +char* +com_shm_get_addr( +/*=============*/ + com_shm_t* area) +{ + return((char*)area + sizeof(com_shm_info_t)); +} + +UNIV_INLINE +byte* +com_shm_get_data( +/*=============*/ + com_shm_t* area) +{ + return((byte*)com_shm_get_addr(area) + com_shm_get_addr_len(area)); +} + +/************************************************************************* +Initializes the shared memory communication system for this +process. */ +UNIV_INLINE +void +com_shm_init(void) +/*==============*/ +{ + mutex_create(&com_shm_destination_mutex); + + mutex_set_level(&com_shm_destination_mutex, SYNC_ANY_LATCH); + + com_shm_destination_cache = hash_create(1000); + + UT_LIST_INIT(com_shm_destination_list); + + com_shm_initialized = TRUE; +} + +/************************************************************************* +Reserves the ip mutex of the shared memory area of an endpoint. */ +UNIV_INLINE +void +com_shm_enter( +/*==========*/ + com_shm_endpoint_t* ep) +{ + ulint ret; + + ret = ip_mutex_enter(ep->ip_mutex, 10000000); + + if (ret != 0) { + mutex_list_print_info(); + + ut_error; + } +} + +/************************************************************************* +Releases the ip mutex of the shared memory area of an endpoint. */ +UNIV_INLINE +void +com_shm_exit( +/*=========*/ + com_shm_endpoint_t* ep) +{ + ip_mutex_exit(ep->ip_mutex); +} + +/************************************************************************* +Looks for the given address in the cached destination addresses. */ +UNIV_INLINE +com_shm_endpoint_t* +com_shm_destination_cache_search( +/*=============================*/ + /* out: cached endpoint structure if found, else NULL */ + char* addr, /* in: destination address */ + ulint len) /* in: address length */ +{ + com_shm_endpoint_t* ep; + ulint fold; + + fold = ut_fold_binary((byte*)addr, len); +/* + printf("Searching dest. cache %s %lu fold %lu\n", addr, len, fold); +*/ + mutex_enter(&com_shm_destination_mutex); + + HASH_SEARCH(addr_hash, com_shm_destination_cache, fold, ep, + ((ep->addr_len == len) + && (0 == ut_memcmp(addr, ep->addr, len)))); + + mutex_exit(&com_shm_destination_mutex); + + return(ep); +} + +/************************************************************************* +Inserts the given endpoint structure in the cached destination addresses. */ +static +void +com_shm_destination_cache_insert( +/*=============================*/ + com_shm_endpoint_t* ep) /* in: endpoint struct to insert */ +{ + ulint fold; + + fold = ut_fold_binary((byte*)(ep->addr), ep->addr_len); + + mutex_enter(&com_shm_destination_mutex); + + /* Add to hash table */ + HASH_INSERT(com_shm_endpoint_t, + addr_hash, com_shm_destination_cache, fold, ep); + + UT_LIST_ADD_LAST(list, com_shm_destination_list, ep); + +/* printf("Inserting to dest. cache %s %lu fold %lu\n", ep->addr, + ep->addr_len, fold); +*/ + mutex_exit(&com_shm_destination_mutex); +} + +/************************************************************************* +Frees the endpoint structs in the destination cache if the bind count is zero. +If it is not, some send operation may just be using a cached endpoint and it +cannot be freed. */ +static +void +com_shm_destination_cache_no_binds(void) +/*====================================*/ +{ + com_shm_endpoint_t* ep; + ulint fold; + + mutex_enter(&com_shm_destination_mutex); + + if (com_shm_bind_count != 0) { + mutex_exit(&com_shm_destination_mutex); + + return; + } + + while (UT_LIST_GET_LEN(com_shm_destination_list) != 0) { + + ep = UT_LIST_GET_FIRST(com_shm_destination_list); + + UT_LIST_REMOVE(list, com_shm_destination_list, ep); + + fold = ut_fold_binary((byte*)ep->addr, ep->addr_len); +/* + printf("Deleting from dest. cache %s %lu fold %lu\n", + ep->addr, + ep->addr_len, fold); +*/ + HASH_DELETE(com_shm_endpoint_t, addr_hash, + com_shm_destination_cache, fold, ep); + + com_shm_endpoint_free(ep); + } + + mutex_exit(&com_shm_destination_mutex); +} + +/*********************************************************************** +Unbinds an endpoint at the time of freeing. */ +static +void +com_shm_unbind( +/*===========*/ + com_shm_endpoint_t* ep) /* in: endpoint */ +{ + com_shm_t* map; + + map = com_shm_endpoint_get_map(ep); + + /* Mark the shared memory area invalid */ + + com_shm_set_valid(map, 0); + + /* Decrement the count of bindings */ + + mutex_enter(&com_shm_destination_mutex); + + com_shm_bind_count--; + + mutex_exit(&com_shm_destination_mutex); + + /* If there are no binds left, free the cached endpoints */ + + com_shm_destination_cache_no_binds(); +} + +/************************************************************************* +Creates a communications endpoint. */ + +com_shm_endpoint_t* +com_shm_endpoint_create(void) +/*=========================*/ + /* out, own: communications endpoint, NULL if + did not succeed */ +{ + com_shm_endpoint_t* ep; + + if (!com_shm_initialized) { + + com_shm_init(); + } + + ep = mem_alloc(sizeof(com_shm_endpoint_t)); + + com_shm_endpoint_set_owns_shm(ep, FALSE); + com_shm_endpoint_set_addr(ep, NULL); + com_shm_endpoint_set_size(ep, 0); + + return(ep); +} + +/************************************************************************* +Frees a communications endpoint. */ + +ulint +com_shm_endpoint_free( +/*==================*/ + /* out: O if succeed, else error number */ + com_shm_endpoint_t* ep) /* in, own: communications endpoint */ +{ + com_shm_t* map; + + ut_ad(ep); + + if (com_shm_endpoint_get_addr(ep) != NULL) { + + map = com_shm_endpoint_get_map(ep); + + if (com_shm_endpoint_get_owns_shm(ep)) { + + com_shm_unbind(ep); + } + + /* We do not destroy the data structures in the shared memory + area, because we cannot be sure that there is currently no + process accessing it. Therefore we just close the ip_mutex + residing in the area. */ + + ip_mutex_close(ep->ip_mutex); + + os_event_free(com_shm_endpoint_get_not_empty(ep)); + os_event_free(com_shm_endpoint_get_empty(ep)); + + os_shm_unmap(map); + os_shm_free(com_shm_endpoint_get_shm(ep)); + + mem_free(com_shm_endpoint_get_addr(ep)); + } + + mem_free(ep); + + return(0); +} + +/************************************************************************* +Sets an option, like the maximum datagram size for an endpoint. +The options may vary depending on the endpoint type. */ + +ulint +com_shm_endpoint_set_option( +/*========================*/ + /* out: 0 if succeed, else error number */ + com_shm_endpoint_t* ep, /* in: endpoint */ + ulint optno, /* in: option number, only + COM_OPT_MAX_DGRAM_SIZE currently supported */ + byte* optval, /* in: pointer to a buffer containing the + option value to set */ + ulint optlen) /* in: option value buffer length */ +{ + ulint size; + + UT_NOT_USED(optlen); + + ut_ad(ep); + ut_a(optno == COM_OPT_MAX_DGRAM_SIZE); + ut_ad(NULL == com_shm_endpoint_get_addr(ep)); + + size = *((ulint*)optval); + + ut_ad(size > 0); + + com_shm_endpoint_set_size(ep, size); + + return(0); +} + +/************************************************************************* +This function is used either to create a new shared memory area or open an +existing one, but this does not do the operations necessary with the ip mutex. +They are performed in com_shm_bind or com_shm_open which call this function. */ +static +ulint +com_shm_create_or_open( +/*===================*/ + /* out: 0 if succeed, else error number */ + com_shm_endpoint_t* ep, /* in: communications endpoint */ + char* name, /* in: address name */ + ulint len) /* in: address name length */ +{ + os_shm_t shm; + com_shm_t* map; + os_event_t event_ne; + os_event_t event_em; + char* buf; + + ut_ad(ep); + ut_ad(name); + ut_ad(len > 0); + + buf = mem_alloc(COM_MAX_ADDR_LEN + 20); + + ut_memcpy(buf, name, len); + + ut_strcpy(buf + len, "_IBSHM"); + + shm = os_shm_create(sizeof(com_shm_info_t) + COM_MAX_ADDR_LEN + + com_shm_endpoint_get_size(ep), buf); + if (shm == NULL) { + + return(COM_ERR_NOT_SPECIFIED); + } + + map = os_shm_map(shm); + + if (map == NULL) { + os_shm_free(shm); + + return(COM_ERR_NOT_SPECIFIED); + } + + ut_strcpy(buf + len, "_IBSHM_EV_NE"), + + event_ne = os_event_create_auto(buf); + + ut_ad(event_ne); + + ut_strcpy(buf + len, "_IBSHM_EV_EM"), + + event_em = os_event_create_auto(buf); + + ut_ad(event_em); + + com_shm_endpoint_set_shm(ep, shm); + com_shm_endpoint_set_map(ep, map); + + com_shm_endpoint_set_not_empty(ep, event_ne); + com_shm_endpoint_set_empty(ep, event_em); + + com_shm_endpoint_set_addr(ep, buf); + com_shm_endpoint_set_addr_len(ep, len); + + return(0); +} + +/************************************************************************* +Opens a shared memory area for communication. */ +static +ulint +com_shm_open( +/*=========*/ + /* out: 0 if succeed, else error number */ + com_shm_endpoint_t* ep, /* in: communications endpoint */ + char* name, /* in: address name */ + ulint len) /* in: address name length */ +{ + ip_mutex_hdl_t* ip_hdl; + com_shm_t* map; + ulint ret; + char buf[COM_MAX_ADDR_LEN + 20]; + + ret = com_shm_create_or_open(ep, name, len); + + if (ret != 0) { + + return(ret); + } + + map = com_shm_endpoint_get_map(ep); + + /* Open the interprocess mutex to protect the shared memory area */ + + ut_memcpy(buf, name, len); + ut_strcpy(buf + len, "_IBSHM_MTX"); + + ret = ip_mutex_open(com_shm_get_ip_mutex(map), buf, &ip_hdl); + + if (ret != 0) { + + return(COM_ERR_NOT_SPECIFIED); + } + + ep->ip_mutex = ip_hdl; + + return(0); +} + +/************************************************************************* +Creates a shared memory area for communication. */ + +ulint +com_shm_bind( +/*=========*/ + /* out: 0 if succeed, else error number */ + com_shm_endpoint_t* ep, /* in: communications endpoint */ + char* name, /* in: address name */ + ulint len) /* in: address name length */ +{ + com_shm_t* map; + ulint ret; + char buf[COM_MAX_ADDR_LEN + 20]; + ip_mutex_hdl_t* ip_hdl; + + if (com_shm_endpoint_get_size(ep) == 0) { + + return(COM_ERR_MAX_DATAGRAM_SIZE_NOT_SET); + } + + ret = com_shm_create_or_open(ep, name, len); + + if (ret != 0) { + + return(ret); + } + + map = com_shm_endpoint_get_map(ep); + + /* Create the interprocess mutex to protect the shared memory area */ + + ut_memcpy(buf, name, len); + ut_strcpy(buf + len, "_IBSHM_MTX"); + + ret = ip_mutex_create(com_shm_get_ip_mutex(map), buf, &ip_hdl); + + if (ret != 0) { + + return(COM_ERR_NOT_SPECIFIED); + } + + /* This endpoint structure owns the shared memory area */ + + com_shm_endpoint_set_owns_shm(ep, TRUE); + ep->ip_mutex = ip_hdl; + + mutex_enter(&com_shm_destination_mutex); + + /* Increment the count of successful bindings */ + + com_shm_bind_count++; + + mutex_exit(&com_shm_destination_mutex); + + com_shm_set_not_empty(map, FALSE); + com_shm_set_empty_waiters(map, 0); + com_shm_set_max_len(map, com_shm_endpoint_get_size(ep)); + + com_shm_set_valid(map, COM_SHM_VALID); + + os_event_set(com_shm_endpoint_get_empty(ep)); + + return(0); +} + +/************************************************************************* +Waits for a datagram to arrive at an endpoint. */ + +ulint +com_shm_recvfrom( +/*=============*/ + /* out: 0 if succeed, else error number */ + com_shm_endpoint_t* ep, /* in: communications endpoint */ + byte* buf, /* out: datagram buffer; the buffer is + supplied by the caller */ + ulint buf_len,/* in: datagram buffer length */ + ulint* len, /* out: datagram length */ + char* from, /* out: address name buffer; the buffer is + supplied by the caller */ + ulint from_len,/* in: address name buffer length */ + ulint* addr_len)/* out: address name length */ +{ + com_shm_t* map; + ulint loop_count; + + map = com_shm_endpoint_get_map(ep); + + loop_count = 0; +loop: + com_shm_system_call_count++; + + /* NOTE: automatic event */ + + os_event_wait(com_shm_endpoint_get_not_empty(ep)); + + loop_count++; + + if (loop_count > 1) { + printf("!!!!!!!!COM_SHM loop count %lu\n", loop_count); + } + + ut_ad(loop_count < 2); + +#ifdef notdefined + if (!com_shm_get_not_empty(map)) { + + /* There was no datagram, give up the time slice + for some writer thread to insert a datagram */ + + com_shm_exit(ep); + + os_thread_yield(); + + com_shm_enter(ep); + } +#endif + com_shm_enter(ep); + + if (!com_shm_get_not_empty(map)) { + /* There was no datagram, wait for the event */ + + com_shm_exit(ep); + + goto loop; + } + + if (com_shm_get_data_len(map) > buf_len) { + + com_shm_exit(ep); + + return(COM_ERR_DATA_BUFFER_TOO_SMALL); + } + + if (com_shm_get_addr_len(map) > from_len) { + + com_shm_exit(ep); + + return(COM_ERR_ADDR_BUFFER_TOO_SMALL); + } + + *len = com_shm_get_data_len(map); + *addr_len = com_shm_get_addr_len(map); + + ut_memcpy(buf, com_shm_get_data(map), *len); + ut_memcpy(from, com_shm_get_addr(map), *addr_len); + + com_shm_set_not_empty(map, FALSE); + + /* If there may be writers queuing to insert the datagram, signal the + empty-event */ + + if (com_shm_get_empty_waiters(map) != 0) { + + com_shm_system_call_count++; + + os_event_set(com_shm_endpoint_get_empty(ep)); + } + + com_shm_exit(ep); + + return(0); +} + +/************************************************************************* +Sends a datagram to the specified destination. */ + +ulint +com_shm_sendto( +/*===========*/ + /* out: 0 if succeed, else error number */ + com_shm_endpoint_t* ep, /* in: communications endpoint */ + byte* buf, /* in: datagram buffer */ + ulint len, /* in: datagram length */ + char* to, /* in: address name buffer */ + ulint tolen) /* in: address name length */ +{ + com_shm_endpoint_t* ep2; + com_shm_t* map; + ulint sender_len; + ulint ret; + ulint loop_count; + + /* Try first to find from the cached destination addresses */ + + ep2 = com_shm_destination_cache_search(to, tolen); + + if (ep2 == NULL) { + /* Did not find it in the cache */ + ep2 = com_shm_endpoint_create(); + + ret = com_shm_open(ep2, to, tolen); + + if (ret != 0) { + com_shm_endpoint_free(ep2); + + return(ret); + } + + /* Insert into the cached destination addresses */ + + com_shm_destination_cache_insert(ep2); + } + + map = com_shm_endpoint_get_map(ep2); + + if (com_shm_get_valid(map) != COM_SHM_VALID) { + + com_shm_exit(ep2); + + return(COM_ERR_DGRAM_NOT_DELIVERED); + } + + if (com_shm_get_max_len(map) < len) { + + com_shm_exit(ep2); + + return(COM_ERR_DATA_TOO_LONG); + } + + /* Optimistically, we first go to see if the datagram area is empty, + without waiting for the empty-event */ + + loop_count = 0; +loop: + loop_count++; + + if (loop_count > 5) { + printf("!!!!!!COM_SHM Notempty loop count %lu\n", loop_count); + } + + ut_ad(loop_count < 100); + + com_shm_enter(ep2); + + if (com_shm_get_not_empty(map)) { + + /* Not empty, we cannot insert a datagram */ + + com_shm_set_empty_waiters(map, + 1 + com_shm_get_empty_waiters(map)); + com_shm_exit(ep2); + + com_shm_system_call_count++; + + /* Wait for the area to become empty */ + /* NOTE: automatic event */ + + ret = os_event_wait_time(com_shm_endpoint_get_empty(ep2), + 10000000); + ut_a(ret == 0); + + com_shm_enter(ep2); + + com_shm_set_empty_waiters(map, + com_shm_get_empty_waiters(map) - 1); + com_shm_exit(ep2); + + goto loop; + } + + sender_len = com_shm_endpoint_get_addr_len(ep); + + com_shm_set_data_len(map, len); + com_shm_set_addr_len(map, sender_len); + + ut_memcpy(com_shm_get_data(map), buf, len); + ut_memcpy(com_shm_get_addr(map), com_shm_endpoint_get_addr(ep), + sender_len); + com_shm_set_not_empty(map, TRUE); +#ifdef notdefined + com_shm_exit(ep2); + + /* Now we give up our time slice voluntarily to give some reader + thread chance to fetch the datagram */ + + os_thread_yield(); + + com_shm_enter(ep2); + + if (com_shm_get_not_empty(map)) { +#endif + com_shm_system_call_count++; + + com_shm_exit(ep2); + + /* Signal the event */ + + os_event_set(com_shm_endpoint_get_not_empty(ep2)); + + return(0); + +#ifdef notdefined + } + + com_shm_exit(ep2); + + return(0); +#endif +} diff --git a/innobase/com/makefilewin b/innobase/com/makefilewin new file mode 100644 index 00000000000..0d2d6d45952 --- /dev/null +++ b/innobase/com/makefilewin @@ -0,0 +1,12 @@ +include ..\include\makefile.i + +com.lib: com0com.obj com0shm.obj + lib -out:..\libs\com.lib com0com.obj com0shm.obj + +com0com.obj: com0com.c + $(CCOM) $(CFL) -c com0com.c + +com0shm.obj: com0shm.c + $(CCOM) $(CFL) -c com0shm.c + + diff --git a/innobase/com/ts/makefile b/innobase/com/ts/makefile new file mode 100644 index 00000000000..01c14737c78 --- /dev/null +++ b/innobase/com/ts/makefile @@ -0,0 +1,19 @@ + + + +include ..\..\makefile.i + +doall: tscom tscli + +tscom: ..\com.lib tscom.c makefile + $(CCOM) $(CFL) -I.. -I..\.. ..\com.lib ..\..\ut.lib ..\..\mem.lib ..\..\sync.lib ..\..\os.lib tscom.c $(LFL) + +tscli: ..\com.lib tscli.c makefile + $(CCOM) $(CFL) -I.. -I..\.. ..\com.lib ..\..\ut.lib ..\..\mem.lib ..\..\sync.lib ..\..\os.lib tscli.c $(LFL) + + + + + + + diff --git a/innobase/com/ts/tscli.c b/innobase/com/ts/tscli.c new file mode 100644 index 00000000000..27a787a0e5c --- /dev/null +++ b/innobase/com/ts/tscli.c @@ -0,0 +1,96 @@ +/************************************************************************ +The test module for communication + +(c) 1995 Innobase Oy + +Created 9/26/1995 Heikki Tuuri +*************************************************************************/ + +#include "../com0com.h" +#include "../com0shm.h" +#include "ut0ut.h" +#include "mem0mem.h" +#include "os0thread.h" +#include "sync0ipm.h" +#include "sync0sync.h" + +byte buf[10000]; +char addr[150]; + +void +test1(void) +/*=======*/ +{ + com_endpoint_t* ep; + ulint ret; + ulint size; + ulint len; + ulint addr_len; + ulint i; + + ep = com_endpoint_create(COM_SHM); + + ut_a(ep); + + size = 8192; + + ret = com_endpoint_set_option(ep, COM_OPT_MAX_DGRAM_SIZE, + (byte*)&size, 0); + + ut_a(ret == 0); + + ret = com_bind(ep, "CLI", 3); + + ut_a(ret == 0); + + printf("Client endpoint created!\n"); + + for (i = 0; i < 10000; i++) { + + ret = com_sendto(ep, (byte*)"Hello from client!\n", 18, "SRV", 3); + + ut_a(ret == 0); + + ret = com_recvfrom(ep, buf, 10000, &len, addr, 150, &addr_len); + + ut_a(ret == 0); + + buf[len] = '\0'; + addr[addr_len] = '\0'; +/* + printf( + "Message of len %lu\n%s \nreceived from address %s of len %lu\n", + len, buf, addr, addr_len); +*/ + } + + ret = com_endpoint_free(ep); + + ut_ad(ret == 0); + + + printf("Count of extra system calls in com_shm %lu\n", + com_shm_system_call_count); + printf("Count of extra system calls in ip_mutex %lu\n", + ip_mutex_system_call_count); +} + +void +main(void) +/*======*/ +{ + ulint tm, oldtm; + + sync_init(); + mem_init(); + + oldtm = ut_clock(); + + test1(); + + ut_ad(mem_all_freed()); + + tm = ut_clock(); + printf("Wall clock time for test %ld milliseconds\n", tm - oldtm); + printf("TESTS COMPLETED SUCCESSFULLY!\n"); +} diff --git a/innobase/com/ts/tscom.c b/innobase/com/ts/tscom.c new file mode 100644 index 00000000000..a02db40efa7 --- /dev/null +++ b/innobase/com/ts/tscom.c @@ -0,0 +1,94 @@ +/************************************************************************ +The test module for communication + +(c) 1995 Innobase Oy + +Created 9/26/1995 Heikki Tuuri +*************************************************************************/ + +#include "../com0com.h" +#include "../com0shm.h" +#include "ut0ut.h" +#include "mem0mem.h" +#include "os0thread.h" +#include "sync0ipm.h" +#include "sync0sync.h" + +byte buf[10000]; +char addr[150]; + +void +test1(void) +/*=======*/ +{ + com_endpoint_t* ep; + ulint ret; + ulint size; + ulint len; + ulint addr_len; + ulint i; + + ep = com_endpoint_create(COM_SHM); + + ut_a(ep); + + size = 8192; + + ret = com_endpoint_set_option(ep, COM_OPT_MAX_DGRAM_SIZE, + (byte*)&size, 0); + + ut_a(ret == 0); + + ret = com_bind(ep, "SRV", 3); + + ut_a(ret == 0); + + printf("Server endpoint created!\n"); + + for (i = 0; i < 50000; i++) { + + ret = com_recvfrom(ep, buf, 10000, &len, addr, 150, &addr_len); + + ut_a(ret == 0); + + buf[len] = '\0'; + addr[addr_len] = '\0'; +/* + printf( + "Message of len %lu\n%s \nreceived from address %s of len %lu\n", + len, buf, addr, addr_len); +*/ + ret = com_sendto(ep, (byte*)"Hello from server!\n", 18, "CLI", 3); + + ut_a(ret == 0); + } + + ret = com_endpoint_free(ep); + + ut_ad(ret == 0); + + printf("Count of extra system calls in com_shm %lu\n", + com_shm_system_call_count); + printf("Count of extra system calls in ip_mutex %lu\n", + ip_mutex_system_call_count); +} + +void +main(void) +/*======*/ +{ + ulint tm, oldtm; + + sync_init(); + mem_init(); + + oldtm = ut_clock(); + + test1(); + + ut_ad(mem_all_freed()); + + tm = ut_clock(); + printf("Wall clock time for test %ld milliseconds\n", tm - oldtm); + printf("TESTS COMPLETED SUCCESSFULLY!\n"); +} |