00001
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <errno.h>
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include <misc/debug.h>
00013 #include <misc/errno.h>
00014 #include <core/tx.h>
00015 #include <core/config.h>
00016 #include <core/koa.h>
00017 #include <core/buffer.h>
00018 #include <core/stats.h>
00019 #include <libc/syscalls.h>
00020 #include <core/txdesc.h>
00021 #include <xcalls/xcalls.h>
00022
00023
00024 typedef struct x_close_commit_args_s x_close_commit_args_t;
00025
00026 struct x_close_commit_args_s {
00027 int fd;
00028 txc_koa_t *koa;
00029 };
00030
00031
00032 static
00033 void
00034 x_close_commit(void *args, int *result)
00035 {
00036 int local_errno = 0;
00037 x_close_commit_args_t *myargs = (x_close_commit_args_t *) args;
00038 txc_koamgr_t *koamgr;
00039 txc_result_t xret;
00040
00041 koamgr = txc_koa_get_koamgr(myargs->koa);
00042 txc_koa_lock_alias_cache(koamgr);
00043 txc_koa_lock_fd(koamgr, myargs->fd);
00044 xret = txc_koa_detach_fd(myargs->koa, myargs->fd, 0);
00045 if (xret == TXC_R_SUCCESS) {
00046 if (txc_libc_close(myargs->fd) < 0) {
00047 local_errno = errno;
00048 }
00049 } else {
00050 local_errno = EBADF;
00051
00052 }
00053 txc_koa_unlock_fd(koamgr, myargs->fd);
00054 txc_koa_unlock_alias_cache(koamgr);
00055 if (result) {
00056 *result = local_errno;
00057 }
00058 }
00059
00060
00073 int
00074 XCALL_DEF(x_close)(int fildes, int *result)
00075 {
00076 txc_tx_t *txd;
00077 txc_koamgr_t *koamgr = txc_g_koamgr;
00078 txc_koa_t *koa;
00079 txc_sentinel_t *sentinel;
00080 txc_result_t xret;
00081 int ret;
00082 x_close_commit_args_t *args_commit;
00083 int local_result = 0;
00084
00085 txd = txc_tx_get_txd();
00086
00087 switch(txc_tx_get_xactstate(txd)) {
00088 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00089 txc_koa_lock_fd(koamgr, fildes);
00090 xret = txc_koa_lookup_fd2koa(koamgr, fildes, &koa);
00091 if (xret == TXC_R_FAILURE) {
00092
00093
00094
00095
00096 txc_koa_unlock_fd(koamgr, fildes);
00097 local_result = EBADF;
00098 ret = -1;
00099 goto done;
00100 }
00101
00102 sentinel = txc_koa_get_sentinel(koa);
00103 xret = txc_sentinel_tryacquire(txd, sentinel, TXC_SENTINEL_ACQUIREONRETRY);
00104 if (xret == TXC_R_BUSYSENTINEL) {
00105 txc_koa_unlock_fd(koamgr, fildes);
00106 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00107 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00108 } else {
00109 txc_koa_unlock_fd(koamgr, fildes);
00110 }
00111
00112 args_commit = (x_close_commit_args_t *)
00113 txc_buffer_linear_malloc(txd->buffer_linear,
00114 sizeof(x_close_commit_args_t));
00115 if (args_commit == NULL) {
00116 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00117 }
00118 args_commit->koa = koa;
00119 args_commit->fd = fildes;
00120
00121 txc_tx_register_commit_action(txd, x_close_commit,
00122 (void *) args_commit, result,
00123 TXC_KOA_DESTROY_COMMIT_ACTION_ORDER);
00124
00125 txc_koa_unlock_fd(koamgr, fildes);
00126 ret = 0;
00127 txc_stats_txstat_increment(txd, XCALL, x_close, 1);
00128 break;
00129 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00130 case TXC_XACTSTATE_NONTRANSACTIONAL:
00131
00132
00133
00134
00135
00136
00137 txc_koa_lock_alias_cache(koamgr);
00138 if ((ret = txc_libc_close(fildes)) < 0) {
00139 txc_koa_unlock_alias_cache(koamgr);
00140 local_result = errno;
00141 goto done;
00142 }
00143 xret = txc_koa_lookup_fd2koa(koamgr, fildes, &koa);
00144 txc_koa_detach_fd(koa, fildes, 1);
00145 txc_koa_unlock_alias_cache(koamgr);
00146 ret = fildes;
00147 }
00148 done:
00149 if (result) {
00150 *result = local_result;
00151 }
00152 return ret;
00153 }