diff options
author | gmcdonald | 2010-02-13 01:32:03 +0000 |
---|---|---|
committer | gmcdonald | 2010-02-13 01:32:03 +0000 |
commit | 0425aadc78680e53000fd0108b540d6eca048516 (patch) | |
tree | 8ec7ab8e015d454c5ec586dfc91e05a2dce1cfc0 /util/src/platforms/unix | |
download | axis2c-0425aadc78680e53000fd0108b540d6eca048516.tar.gz axis2c-0425aadc78680e53000fd0108b540d6eca048516.tar.bz2 |
Moving axis svn, part of TLP move INFRA-2441
git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'util/src/platforms/unix')
-rw-r--r-- | util/src/platforms/unix/Makefile.am | 8 | ||||
-rw-r--r-- | util/src/platforms/unix/date_time_util_unix.c | 31 | ||||
-rw-r--r-- | util/src/platforms/unix/thread_unix.c | 362 | ||||
-rw-r--r-- | util/src/platforms/unix/uuid_gen_unix.c | 345 |
4 files changed, 746 insertions, 0 deletions
diff --git a/util/src/platforms/unix/Makefile.am b/util/src/platforms/unix/Makefile.am new file mode 100644 index 0000000..6506a01 --- /dev/null +++ b/util/src/platforms/unix/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libaxis2_unix.la + +libaxis2_unix_la_SOURCES = uuid_gen_unix.c\ + thread_unix.c date_time_util_unix.c + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/include/platforms \ + -I$(top_builddir)/include/platforms/unix diff --git a/util/src/platforms/unix/date_time_util_unix.c b/util/src/platforms/unix/date_time_util_unix.c new file mode 100644 index 0000000..e0c4a28 --- /dev/null +++ b/util/src/platforms/unix/date_time_util_unix.c @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <platforms/unix/axutil_date_time_util_unix.h> + +AXIS2_EXTERN int AXIS2_CALL +axis2_platform_get_milliseconds() +{ + struct timeb t_current; + int milliseconds; + + ftime(&t_current); + milliseconds = t_current.millitm; + + return milliseconds; + +} diff --git a/util/src/platforms/unix/thread_unix.c b/util/src/platforms/unix/thread_unix.c new file mode 100644 index 0000000..ccedd06 --- /dev/null +++ b/util/src/platforms/unix/thread_unix.c @@ -0,0 +1,362 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> +#include "axutil_thread_unix.h" + +AXIS2_EXTERN axutil_threadattr_t *AXIS2_CALL +axutil_threadattr_create( + axutil_allocator_t * allocator) +{ + int stat = 0; + axutil_threadattr_t *new = NULL; + + new = AXIS2_MALLOC(allocator, sizeof(axutil_threadattr_t)); + if(!new) + { + return NULL; + } + stat = pthread_attr_init(&(new->attr)); + + if(stat != 0) + { + AXIS2_FREE(allocator, new); + return NULL; + } + return new; +} + +/* Destroy the threadattr object */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +threadattr_cleanup( + void *data) +{ + axutil_threadattr_t *attr = data; + int rv; + + rv = pthread_attr_destroy(&(attr->attr)); + + if(0 != rv) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +#define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE) + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_threadattr_detach_set( + axutil_threadattr_t * attr, + axis2_bool_t detached) +{ + if(0 == pthread_attr_setdetachstate(&(attr->attr), DETACH_ARG(detached))) + { + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_threadattr_detach_get( + axutil_threadattr_t * attr) +{ + int state = 0; + pthread_attr_getdetachstate(&(attr->attr), &state); + if(state == 1) + { + return AXIS2_TRUE; + } + return AXIS2_FALSE; +} + +static void * +dummy_worker( + void *opaque) +{ + axutil_thread_t *thread = (axutil_thread_t *)opaque; + return thread->func(thread, thread->data); +} + +AXIS2_EXTERN axutil_thread_t *AXIS2_CALL +axutil_thread_create( + axutil_allocator_t * allocator, + axutil_threadattr_t * attr, + axutil_thread_start_t func, + void *data) +{ + axis2_status_t stat; + pthread_attr_t *temp = NULL; + axutil_thread_t *new = NULL; + + new = (axutil_thread_t *)AXIS2_MALLOC(allocator, sizeof(axutil_thread_t)); + + if(!new) + { + return NULL; + } + new->td = (pthread_t *)AXIS2_MALLOC(allocator, sizeof(pthread_t)); + if(!new->td) + { + return NULL; + } + + new->data = data; + new->func = func; + new->try_exit = AXIS2_FALSE; + + if(attr) + { + temp = &(attr->attr); + } + else + { + temp = NULL; + } + + if((stat = pthread_create(new->td, temp, dummy_worker, new)) == 0) + { + return new; + } + return NULL; +} + +AXIS2_EXTERN axis2_os_thread_t AXIS2_CALL +axis2_os_thread_current( + void) +{ + return pthread_self(); +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_os_thread_equal( + axis2_os_thread_t tid1, + axis2_os_thread_t tid2) +{ + return pthread_equal(tid1, tid2); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_exit( + axutil_thread_t * thd, + axutil_allocator_t * allocator) +{ + axis2_bool_t same_thread = AXIS2_TRUE; + if(thd) + { + while(!thd->try_exit) + { + sleep(1); + } + + if(thd->td) + { + same_thread = pthread_equal(pthread_self(), *thd->td); + if(!same_thread) + { + pthread_kill(*(thd->td), 0); + axutil_thread_join(thd); + } + AXIS2_FREE(allocator, thd->td); + } + AXIS2_FREE(allocator, thd); + } + if(same_thread) + { + pthread_exit(NULL); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_join( + axutil_thread_t * thd) +{ + void *thread_stat; + if(0 == pthread_join(*(thd->td), (void *)(&thread_stat))) + { + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_detach( + axutil_thread_t * thd) +{ + if(0 == pthread_detach(*(thd->td))) + { + thd->try_exit = AXIS2_TRUE; + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +void +axutil_thread_yield( + void) +{ + return; +} + +/** + * function is used to allocate a new key. This key now becomes valid for all threads in our process. + * When a key is created, the value it points to defaults to NULL. Later on each thread may change + * its copy of the value as it wishes. + */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_key_create( + axutil_threadkey_t * axis2_key) +{ + int rc = -1; + pthread_key_t key = axis2_key->key; + rc = pthread_key_create(&key, NULL); + if(0 == rc) + return AXIS2_SUCCESS; + else + return AXIS2_FAILURE; +} + +/** + * This function is used to get the value of a given key + * @return void*. A key's value is simply a void pointer (void*) + */ +AXIS2_EXTERN void *AXIS2_CALL +axutil_thread_getspecific( + axutil_threadkey_t * axis2_key) +{ + void *value = NULL; + pthread_key_t key = axis2_key->key; + value = pthread_getspecific(key); + return value; +} + +/** + * This function is used to get the value of a given key + * @param keys value. A key's value is simply a void pointer (void*), so we can + * store in it anything that we want + */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_setspecific( + axutil_threadkey_t * axis2_key, + void *value) +{ + int rc = -1; + pthread_key_t key = axis2_key->key; + rc = pthread_setspecific(key, value); + if(0 == rc) + return AXIS2_SUCCESS; + else + return AXIS2_FAILURE; +} + +AXIS2_EXTERN void AXIS2_CALL +axutil_thread_key_free( + axutil_threadkey_t * axis2_key) +{ + pthread_key_t key = axis2_key->key; + pthread_key_delete(key); +} + +AXIS2_EXTERN axis2_os_thread_t *AXIS2_CALL +axis2_os_thread_get( + axutil_thread_t * thd) +{ + if(!thd) + { + return NULL; + } + return thd->td; +} + +AXIS2_EXTERN axutil_thread_once_t *AXIS2_CALL +axutil_thread_once_init( + axutil_allocator_t * allocator) +{ +#if defined(AXIS2_SOLARIS) && (__GNUC__ <= 3) + static const pthread_once_t once_init = + { PTHREAD_ONCE_INIT}; +#else + static const pthread_once_t once_init = PTHREAD_ONCE_INIT; +#endif + axutil_thread_once_t *control = AXIS2_MALLOC(allocator, sizeof(axutil_thread_once_t)); + if(!control) + { + return NULL;; + } + (control)->once = once_init; + return control; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_once( + axutil_thread_once_t * control, + void + (*func)( + void)) +{ + return pthread_once(&(control->once), func); +} + +/*************************Thread locking functions*****************************/ +AXIS2_EXTERN axutil_thread_mutex_t *AXIS2_CALL +axutil_thread_mutex_create( + axutil_allocator_t * allocator, + unsigned int flags) +{ + axutil_thread_mutex_t *new_mutex = NULL; + + new_mutex = AXIS2_MALLOC(allocator, sizeof(axutil_thread_mutex_t)); + new_mutex->allocator = allocator; + + if(pthread_mutex_init(&(new_mutex->mutex), NULL) != 0) + { + AXIS2_FREE(allocator, new_mutex); + return NULL; + } + return new_mutex; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_mutex_lock( + axutil_thread_mutex_t * mutex) +{ + return pthread_mutex_lock(&(mutex->mutex)); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_mutex_unlock( + axutil_thread_mutex_t * mutex) +{ + if(pthread_mutex_unlock(&(mutex->mutex)) != 0) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_mutex_destroy( + axutil_thread_mutex_t * mutex) +{ + if(0 != pthread_mutex_destroy(&(mutex->mutex))) + { + return AXIS2_FAILURE; + } + AXIS2_FREE(mutex->allocator, mutex); + return AXIS2_SUCCESS; +} diff --git a/util/src/platforms/unix/uuid_gen_unix.c b/util/src/platforms/unix/uuid_gen_unix.c new file mode 100644 index 0000000..cdc2544 --- /dev/null +++ b/util/src/platforms/unix/uuid_gen_unix.c @@ -0,0 +1,345 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include <sys/ioctl.h> +#include <string.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <netdb.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> + +#ifdef HAVE_LINUX_IF_H +# include <linux/if.h> +#else +# ifdef HAVE_NET_IF_H +# include <sys/sockio.h> +# include <net/if.h> +# include <net/if_arp.h> +# endif +# ifdef HAVE_NET_IF_TYPES_H +# include <net/if_types.h> +# endif +# ifdef HAVE_NET_IF_DL_H +# include <net/if_dl.h> +# endif +#endif +#ifdef HAVE_GETIFADDRS +#include <ifaddrs.h> +#endif +#include <platforms/unix/axutil_uuid_gen_unix.h> +#include <platforms/axutil_platform_auto_sense.h> + +/* We need these static variables to track throughout the program execution */ +static axis2_bool_t axutil_uuid_gen_is_first = AXIS2_TRUE; +static struct axutil_uuid_st axutil_uuid_static; + +axutil_uuid_t *AXIS2_CALL +axutil_uuid_gen_v1() +{ + struct timeval time_now; + struct timeval tv; + unsigned long long time_val; + unsigned long long time_val2; + unsigned short int clck = 0; + axutil_uuid_t *ret_uuid = NULL; + unsigned short int time_high_version = 0; + + if(AXIS2_TRUE == axutil_uuid_gen_is_first) + { + char *mac_addr = axutil_uuid_get_mac_addr(); + memcpy(axutil_uuid_static.mac, mac_addr, 6); + axutil_uuid_static.time_seq = 0; + axutil_uuid_static.clock = 0; + free(mac_addr); + axutil_uuid_gen_is_first = AXIS2_FALSE; + } + /* + * GENERATE TIME + */ + + /* determine current system time and sequence counter */ + if(gettimeofday(&time_now, NULL) == -1) + return NULL; + + /* check whether system time changed since last retrieve */ + if(!(time_now.tv_sec == axutil_uuid_static.time_last.tv_sec && time_now.tv_usec + == axutil_uuid_static.time_last.tv_usec)) + { + /* reset time sequence counter and continue */ + axutil_uuid_static.time_seq = 0; + } + + /* until we are out of UUIDs per tick, increment + the time/tick sequence counter and continue */ + while(axutil_uuid_static.time_seq < UUIDS_PER_TICK) + { + axutil_uuid_static.time_seq++; + } + /* sleep for 1000ns (1us) */ + tv.tv_sec = 0; + tv.tv_usec = 1; + /* + The following select causes severe performance problems. + Hence commenting out. I am not sure why this is required. - Samisa. + select(0, NULL, NULL, NULL, &tv); */ + + time_val = (unsigned long long)time_now.tv_sec * 10000000ull; + time_val += (unsigned long long)time_now.tv_usec * 10ull; + + ret_uuid = malloc(sizeof(axutil_uuid_t)); + + time_val += UUID_TIMEOFFSET; + /* compensate for low resolution system clock by adding + the time/tick sequence counter */ + if(axutil_uuid_static.time_seq > 0) + time_val += (unsigned long long)axutil_uuid_static.time_seq; + + time_val2 = time_val; + ret_uuid->time_low = (unsigned long)time_val2; + time_val2 >>= 32; + ret_uuid->time_mid = (unsigned short int)time_val2; + time_val2 >>= 16; + time_high_version = (unsigned short int)time_val2; + + /* store the 60 LSB of the time in the UUID and make version 1 */ + time_high_version <<= 4; + time_high_version &= 0xFFF0; + time_high_version |= 0x0001; + ret_uuid->time_high_version = time_high_version; + + /* + * GENERATE CLOCK + */ + + /* retrieve current clock sequence */ + clck = axutil_uuid_static.clock; + + /* generate new random clock sequence (initially or if the + time has stepped backwards) or else just increase it */ + if(clck == 0 || (time_now.tv_sec < axutil_uuid_static.time_last.tv_sec || (time_now.tv_sec + == axutil_uuid_static.time_last.tv_sec && time_now.tv_usec + < axutil_uuid_static.time_last.tv_usec))) + { + srand(time_now.tv_usec); + clck = rand(); + } + else + { + clck++; + } + clck %= (2 << 14); + + /* store back new clock sequence */ + axutil_uuid_static.clock = clck; + + clck &= 0x1FFF; + clck |= 0x2000; + + /* + * FINISH + */ + /* remember current system time for next iteration */ + axutil_uuid_static.time_last.tv_sec = time_now.tv_sec; + axutil_uuid_static.time_last.tv_usec = time_now.tv_usec; + + if(!ret_uuid) + { + return NULL; + } + ret_uuid->clock_variant = clck; + memcpy(ret_uuid->mac_addr, axutil_uuid_static.mac, 6); + return ret_uuid; +} + +axis2_char_t *AXIS2_CALL +axutil_platform_uuid_gen( + char *s) +{ + axutil_uuid_t *uuid_struct = NULL; + axis2_char_t *uuid_str = NULL; + unsigned char mac[7]; + char mac_hex[13]; + + if(!s) + { + return NULL; + } + uuid_struct = axutil_uuid_gen_v1(); + if(!uuid_struct) + { + return NULL; + } + uuid_str = s; + if(!uuid_str) + { + return NULL; + } + memcpy(mac, uuid_struct->mac_addr, 6); + sprintf(mac_hex, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + sprintf(uuid_str, "%08x-%04x-%04x-%04x-%s", uuid_struct->time_low, uuid_struct->time_mid, + uuid_struct->time_high_version, uuid_struct->clock_variant, mac_hex); + free(uuid_struct); + uuid_struct = NULL; + return uuid_str; +} + +#ifdef HAVE_LINUX_IF_H /* Linux */ + +char *AXIS2_CALL +axutil_uuid_get_mac_addr( +) +{ + struct ifreq ifr; + struct ifreq *IFR; + struct ifconf ifc; + struct sockaddr *sa; + int s = 0; + int i = 0; + char *buffer = NULL; + char buf[1024]; + int ok = AXIS2_FALSE; + + if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + return NULL; + + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + ioctl(s, SIOCGIFCONF, &ifc); + IFR = ifc.ifc_req; + + for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++) + { + strcpy(ifr.ifr_name, IFR->ifr_name); + /*sprintf(ifr.ifr_name, "eth0"); */ + if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) + { + if (!(ifr.ifr_flags & IFF_LOOPBACK)) + { + if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) + { + ok = AXIS2_TRUE; + break; + } + } + } + } + buffer = (char *) malloc(6 * sizeof(char)); + if (ok) + { + sa = (struct sockaddr *) &ifr.ifr_addr; + for (i = 0; i < 6; i++) + buffer[i] = (unsigned char) (sa->sa_data[i] & 0xff); + } + else + { + for (i = 0; i < 6; i++) + buffer[i] = (unsigned char) ((AXIS2_LOCAL_MAC_ADDR[i]) - '0'); + } + close(s); + return buffer; +} + +#else + +#ifdef HAVE_GETIFADDRS /* NetBSD, MacOSX, etc... */ + +#ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +#endif /* !max */ + +char *AXIS2_CALL +axutil_uuid_get_mac_addr( +) +{ + struct ifaddrs *ifap; + struct ifaddrs *ifap_head; + const struct sockaddr_dl *sdl; + unsigned char *ucp; + int i; + char *data_ptr; + + if (getifaddrs(&ifap_head) < 0) + return NULL; + for (ifap = ifap_head; ifap != NULL; ifap = ifap->ifa_next) + { + if (ifap->ifa_addr != NULL && ifap->ifa_addr->sa_family == AF_LINK) + { + sdl = (const struct sockaddr_dl *) (void *) ifap->ifa_addr; + ucp = (unsigned char *) (sdl->sdl_data + sdl->sdl_nlen); + if (sdl->sdl_alen > 0) + { + data_ptr = malloc(6 * sizeof(char)); + for (i = 0; i < 6 && i < sdl->sdl_alen; i++, ucp++) + data_ptr[i] = (unsigned char) (*ucp & 0xff); + + freeifaddrs(ifap_head); + return data_ptr; + } + } + } + freeifaddrs(ifap_head); + return NULL; +} +# else /* Solaris-ish */ + +/* code modified from that posted on: + * http://forum.sun.com/jive/thread.jspa?threadID=84804&tstart=30 + */ + +char *AXIS2_CALL +axutil_uuid_get_mac_addr() +{ + char hostname[MAXHOSTNAMELEN]; + char *data_ptr; + struct hostent *he; + struct arpreq ar; + struct sockaddr_in *sa; + int s; + int i; + + if(gethostname(hostname, sizeof(hostname)) < 0) + return NULL; + if((he = gethostbyname(hostname)) == NULL) + return NULL; + if((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + return NULL; + memset(&ar, 0, sizeof(ar)); + sa = (struct sockaddr_in *)((void *)&(ar.arp_pa)); + sa->sin_family = AF_INET; + memcpy(&(sa->sin_addr), *(he->h_addr_list), sizeof(struct in_addr)); + if(ioctl(s, SIOCGARP, &ar) < 0) + { + close(s); + return NULL; + } + close(s); + if(!(ar.arp_flags & ATF_COM)) + return NULL; + data_ptr = malloc(6 * sizeof(char)); + for(i = 0; i < 6; i++) + data_ptr[i] = (unsigned char)(ar.arp_ha.sa_data[i] & 0xff); + + return data_ptr; +} +# endif +#endif |