00001
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <errno.h>
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include <sys/socket.h>
00013 #include <misc/debug.h>
00014 #include <misc/errno.h>
00015 #include <core/tx.h>
00016 #include <core/config.h>
00017 #include <core/koa.h>
00018 #include <core/buffer.h>
00019 #include <core/txdesc.h>
00020 #include <core/stats.h>
00021 #include <libc/syscalls.h>
00022 #include <xcalls/xcalls.h>
00023
00024
00025 typedef struct x_socket_undo_args_s x_socket_undo_args_t;
00026
00027 struct x_socket_undo_args_s {
00028 int fd;
00029 txc_koa_t *koa;
00030 };
00031
00032
00033 static
00034 void
00035 x_socket_undo(void *args, int *result)
00036 {
00037 int local_errno = 0;
00038 x_socket_undo_args_t *myargs = (x_socket_undo_args_t *) args;
00039 txc_koamgr_t *koamgr;
00040
00041 koamgr = txc_koa_get_koamgr(myargs->koa);
00042 txc_koa_lock_fd(koamgr, myargs->fd);
00043 txc_koa_detach_fd(myargs->koa, myargs->fd, 0);
00044 if (txc_libc_close(myargs->fd) < 0) {
00045 local_errno = errno;
00046 }
00047 txc_koa_unlock_fd(koamgr, myargs->fd);
00048 if (result) {
00049 *result = local_errno;
00050 }
00051 }
00052
00053
00075 int
00076 XCALL_DEF(x_socket)(int domain, int type, int protocol, int *result)
00077 {
00078 int fildes;
00079 txc_tx_t *txd;
00080 txc_koamgr_t *koamgr = txc_g_koamgr;
00081 txc_koa_t *koa;
00082 txc_sentinel_t *sentinel;
00083 txc_result_t xret;
00084 int ret;
00085 x_socket_undo_args_t *args_undo;
00086 int local_result = 0;
00087 int koa_type;
00088
00089 txd = txc_tx_get_txd();
00090
00091 switch(type) {
00092 case SOCK_DGRAM:
00093 koa_type = TXC_KOA_IS_SOCK_DGRAM;
00094 break;
00095 case SOCK_STREAM:
00096 local_result = EINVAL;
00097 ret = -1;
00098 goto done;
00099 }
00100
00101 switch(txc_tx_get_xactstate(txd)) {
00102 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00103 if ((ret = fildes = txc_libc_socket(domain, type, protocol)) < 0) {
00104 local_result = errno;
00105 goto done;
00106 }
00107 txc_koa_create(koamgr, &koa, koa_type, NULL);
00108 txc_koa_lock_fd(koamgr, fildes);
00109 txc_koa_attach_fd(koa, fildes, 0);
00110 sentinel = txc_koa_get_sentinel(koa);
00111 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00112 if (xret != TXC_R_SUCCESS) {
00113 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00114 }
00115
00116 args_undo = (x_socket_undo_args_t *)
00117 txc_buffer_linear_malloc(txd->buffer_linear,
00118 sizeof(x_socket_undo_args_t));
00119 if (args_undo == NULL) {
00120 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00121 }
00122 args_undo->koa = koa;
00123 args_undo->fd = fildes;
00124
00125 txc_tx_register_undo_action (txd, x_socket_undo,
00126 (void *) args_undo, result,
00127 TXC_KOA_CREATE_UNDO_ACTION_ORDER);
00128
00129 txc_koa_unlock_fd(koamgr, fildes);
00130 ret = fildes;
00131 txc_stats_txstat_increment(txd, XCALL, x_socket, 1);
00132 break;
00133 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00134 case TXC_XACTSTATE_NONTRANSACTIONAL:
00135
00136
00137
00138
00139
00140
00141
00142 if ((ret = fildes = txc_libc_socket(domain, type, protocol)) < 0) {
00143 local_result = errno;
00144 goto done;
00145 }
00146 txc_koa_create(koamgr, &koa, koa_type, NULL);
00147 txc_koa_lock_fd(koamgr, fildes);
00148 txc_koa_attach_fd(koa, fildes, 0);
00149 txc_koa_unlock_fd(koamgr, fildes);
00150 ret = fildes;
00151 }
00152 done:
00153 if (result) {
00154 *result = local_result;
00155 }
00156 return ret;
00157 }