00001
00049 #include <sys/types.h>
00050 #include <sys/stat.h>
00051 #include <libc/syscalls.h>
00052 #include <misc/malloc.h>
00053 #include <misc/result.h>
00054 #include <misc/debug.h>
00055 #include <misc/pool.h>
00056 #include <misc/hash_table.h>
00057 #include <misc/mutex.h>
00058 #include <core/config.h>
00059 #include <core/koa.h>
00060 #include <core/sentinel.h>
00061 #include <core/buffer.h>
00062 #include <stdlib.h>
00063 #include <pthread.h>
00064 #include <stddef.h>
00065
00066
00067 typedef struct txc_koa_file_s txc_koa_file_t;
00068 typedef struct txc_koa_sock_dgram_s txc_koa_sock_dgram_t;
00069 typedef struct txc_koa_pipe_read_end_s txc_koa_pipe_read_end_t;
00070
00071
00073 struct txc_koa_file_s {
00074 ino_t st_ino;
00075 dev_t st_dev;
00076 dev_t st_rdev;
00077 };
00078
00079
00081 struct txc_koa_sock_dgram_s {
00082 txc_buffer_circular_t *buffer_circular_input;
00083 };
00084
00085
00087 struct txc_koa_pipe_read_end_s {
00088 txc_buffer_circular_t *buffer_circular_input;
00089 };
00090
00091
00096 struct txc_koa_s {
00097 txc_koamgr_t *manager;
00098 txc_mutex_t mutex;
00099 txc_sentinel_t *sentinel;
00100 struct {
00101 int fd[TXC_MAX_NUM_FDREFS_PER_KOA];
00102 int refcnt;
00103 } fdref;
00104 int refcnt;
00105 int type;
00106 union {
00107 txc_koa_file_t file;
00108 txc_koa_sock_dgram_t sock_dgram;
00109 txc_koa_pipe_read_end_t pipe_read_end;
00110 };
00111 };
00112
00113 typedef struct txc_fd2koa_s txc_fd2koa_t;
00114
00115
00117 struct txc_fd2koa_s {
00118 txc_mutex_t mutex;
00119 txc_koa_t *koa;
00120 };
00121
00122 typedef struct txc_alias_cache_s txc_alias_cache_t;
00123
00124
00133 struct txc_alias_cache_s {
00134 txc_mutex_t mutex;
00135 txc_hash_table_t *hash_tbl;
00136 };
00137
00138
00140 struct txc_koamgr_s {
00141 txc_alias_cache_t alias_cache;
00142 txc_fd2koa_t map[TXC_KOA_MAP_SIZE];
00143 txc_sentinelmgr_t *sentinelmgr;
00145 txc_buffermgr_t *buffermgr;
00148 txc_pool_t *pool_koa_obj;
00150 };
00151
00152
00153 txc_koamgr_t *txc_g_koamgr;
00154
00155
00169 txc_result_t
00170 txc_koamgr_create(txc_koamgr_t **koamgrp,
00171 txc_sentinelmgr_t *sentinelmgr,
00172 txc_buffermgr_t *buffermgr)
00173 {
00174 int i;
00175 txc_result_t result;
00176 txc_koa_t *koa;
00177
00178 *koamgrp = (txc_koamgr_t *) MALLOC(sizeof(txc_koamgr_t));
00179 if (*koamgrp == NULL) {
00180 return TXC_R_NOMEMORY;
00181 }
00182 if ((result = txc_pool_create(&((*koamgrp)->pool_koa_obj),
00183 sizeof(txc_koa_t),
00184 TXC_KOA_NUM,
00185 NULL)) != TXC_R_SUCCESS)
00186 {
00187 FREE(*koamgrp);
00188 return result;
00189 }
00190
00191 if ((result = txc_hash_table_create(&((*koamgrp)->alias_cache.hash_tbl),
00192 TXC_KOA_CACHE_HASHTBL_SIZE,
00193 TXC_BOOL_FALSE)) != TXC_R_SUCCESS)
00194 {
00195 txc_pool_destroy(&((*koamgrp)->pool_koa_obj));
00196 FREE(*koamgrp);
00197 return result;
00198 }
00199
00200 for (i=0; i<TXC_KOA_MAP_SIZE; i++) {
00201 TXC_MUTEX_INIT(&((*koamgrp)->map[i].mutex), NULL);
00202 (*koamgrp)->map[i].koa = NULL;
00203 }
00204
00205 (*koamgrp)->sentinelmgr = sentinelmgr;
00206 (*koamgrp)->buffermgr = buffermgr;
00207
00208
00209 txc_koa_create(*koamgrp, &koa, TXC_KOA_IS_PIPE_READ_END, NULL);
00210 txc_koa_attach_fd(koa, 0, 0);
00211 txc_koa_create(*koamgrp, &koa, TXC_KOA_IS_PIPE_WRITE_END, NULL);
00212 txc_koa_attach_fd(koa, 1, 0);
00213 txc_koa_create(*koamgrp, &koa, TXC_KOA_IS_PIPE_WRITE_END, NULL);
00214 txc_koa_attach_fd(koa, 2, 0);
00215
00216 return TXC_R_SUCCESS;
00217 }
00218
00219
00226 void
00227 txc_koamgr_destroy(txc_koamgr_t **koamgrp)
00228 {
00229 txc_pool_destroy(&((*koamgrp)->pool_koa_obj));
00230 txc_hash_table_destroy(&((*koamgrp)->alias_cache.hash_tbl));
00231 FREE(*koamgrp);
00232 *koamgrp = NULL;
00233 }
00234
00235
00242 txc_result_t
00243 txc_koa_lock_alias_cache(txc_koamgr_t *koamgr)
00244 {
00245 TXC_MUTEX_LOCK(&(koamgr->alias_cache.mutex));
00246 return TXC_R_SUCCESS;
00247 }
00248
00249
00256 txc_result_t
00257 txc_koa_unlock_alias_cache(txc_koamgr_t *koamgr)
00258 {
00259 TXC_MUTEX_UNLOCK(&(koamgr->alias_cache.mutex));
00260 return TXC_R_SUCCESS;
00261 }
00262
00263
00273 static inline
00274 txc_result_t
00275 alias_cache_insert(txc_koamgr_t *koamgr, txc_koa_t *koa)
00276 {
00277 txc_hash_table_t *h = koamgr->alias_cache.hash_tbl;
00278 txc_result_t ret;
00279 ino_t inode_number = koa->file.st_ino;
00280
00281 TXC_ASSERT(koa->type == TXC_KOA_IS_FILE);
00282
00283 if ((ret = txc_hash_table_add(h, (unsigned int) inode_number, (void *) koa))
00284 != TXC_R_SUCCESS)
00285 {
00286 return ret;
00287 }
00288 return TXC_R_SUCCESS;
00289 }
00290
00291
00301 static inline
00302 txc_result_t
00303 alias_cache_remove(txc_koamgr_t *koamgr, txc_koa_t *koa)
00304 {
00305 txc_hash_table_t *h = koamgr->alias_cache.hash_tbl;
00306 txc_result_t ret;
00307 ino_t inode_number = koa->file.st_ino;
00308
00309 if ((ret = txc_hash_table_remove(h, (unsigned int) inode_number, NULL))
00310 != TXC_R_SUCCESS)
00311 {
00312 return ret;
00313 }
00314 return TXC_R_SUCCESS;
00315 }
00316
00317
00326 txc_result_t
00327 txc_koa_alias_cache_lookup_inode(txc_koamgr_t *koamgr, ino_t inode_number, txc_koa_t **koap)
00328 {
00329 txc_koa_t *koa;
00330
00331 if (txc_hash_table_lookup(koamgr->alias_cache.hash_tbl,
00332 (unsigned int) inode_number, (void **) &koa)
00333 != TXC_R_SUCCESS)
00334 {
00335 return TXC_R_NOTEXISTS;
00336 } else {
00337 *koap = koa;
00338 return TXC_R_SUCCESS;
00339 }
00340
00341 }
00342
00343
00357 txc_result_t
00358 txc_koa_create(txc_koamgr_t *koamgr, txc_koa_t **koap, int type, void *args)
00359 {
00360 txc_koa_t *koa;
00361 txc_sentinel_t *sentinel;
00362 txc_result_t result;
00363
00364 if ((result = txc_pool_object_alloc(koamgr->pool_koa_obj,(void **) &koa, 1))
00365 != TXC_R_SUCCESS)
00366 {
00367 TXC_INTERNALERROR("Could not create KOA object\n");
00368 return result;
00369 }
00370 if ((result = txc_sentinel_create(koamgr->sentinelmgr, &sentinel))
00371 != TXC_R_SUCCESS)
00372 {
00373 TXC_INTERNALERROR("Could not create sentinel for KOA object\n");
00374 return result;
00375 }
00376 TXC_MUTEX_INIT(&(koa->mutex), NULL);
00377 koa->manager = koamgr;
00378 koa->sentinel = sentinel;
00379 koa->type = type;
00380 koa->refcnt = 0;
00381 koa->fdref.refcnt = 0;
00382
00383 switch(type) {
00384 case TXC_KOA_IS_FILE:
00385 koa->file.st_ino = (ino_t) args;
00386 break;
00387 case TXC_KOA_IS_SOCK_DGRAM:
00388 txc_buffer_circular_create(koa->manager->buffermgr,
00389 &(koa->sock_dgram.buffer_circular_input));
00390 break;
00391 case TXC_KOA_IS_PIPE_READ_END:
00392 txc_buffer_circular_create(koa->manager->buffermgr,
00393 &(koa->pipe_read_end.buffer_circular_input));
00394 break;
00395 default:
00396 break;
00397 }
00398
00399 *koap = koa;
00400 return TXC_R_SUCCESS;
00401 }
00402
00403
00409 void
00410 txc_koa_destroy(txc_koa_t **koap)
00411 {
00412 txc_koa_t *koa = *koap;
00413
00414
00415
00416
00417
00418 txc_sentinel_detach((*koap)->sentinel);
00419
00420 switch((*koap)->type) {
00421 case TXC_KOA_IS_FILE:
00422 break;
00423 case TXC_KOA_IS_SOCK_DGRAM:
00424 txc_buffer_circular_destroy(&((*koap)->sock_dgram.buffer_circular_input));
00425 break;
00426 case TXC_KOA_IS_PIPE_READ_END:
00427 txc_buffer_circular_destroy(&((*koap)->pipe_read_end.buffer_circular_input));
00428 break;
00429 default:
00430 break;
00431 }
00432 txc_pool_object_free((*koap)->manager->pool_koa_obj,
00433 (void **) &koa, 1);
00434 }
00435
00436
00445 txc_result_t
00446 txc_koa_attach_fd(txc_koa_t *koa, int fd, int lock)
00447 {
00448 txc_koamgr_t *koamgr;
00449 int first_attach;
00450
00451 TXC_ASSERT(koa != NULL);
00452 TXC_ASSERT(fd < TXC_KOA_MAP_SIZE);
00453
00454 koamgr = koa->manager;
00455
00456 if (lock) {
00457 TXC_MUTEX_LOCK(&(koamgr->map[fd].mutex));
00458 }
00459 TXC_ASSERT(koamgr->map[fd].koa == NULL);
00460 koamgr->map[fd].koa = koa;
00461 koa->refcnt++;
00462 first_attach = (koa->refcnt == 1) ? 1 : 0;
00463 if (first_attach) {
00465 if (koa->type == TXC_KOA_IS_FILE) {
00466 alias_cache_insert(koamgr, koa);
00467 }
00468 }
00469
00470 if (koa->fdref.refcnt >= TXC_MAX_NUM_FDREFS_PER_KOA) {
00471 TXC_INTERNALERROR("Reached maximum number of file descriptors per KOA.\n");
00472 }
00473 koa->fdref.fd[koa->fdref.refcnt++] = fd;
00474
00475 TXC_DEBUG_PRINT(TXC_DEBUG_KOA,
00476 "txc_koa_attach_fd: koa = %p, fd = %d, refcnt = %d, sentinel = %p\n",
00477 koa, fd, koa->refcnt, koa->sentinel);
00478
00479 if (lock) {
00480 TXC_MUTEX_UNLOCK(&(koamgr->map[fd].mutex));
00481 }
00482
00483 return TXC_R_SUCCESS;
00484 }
00485
00486
00495 txc_result_t
00496 txc_koa_detach_fd(txc_koa_t *koa, int fd, int lock)
00497 {
00498 int i;
00499 int index = -1;
00500 int last_detach;
00501 txc_koamgr_t *koamgr;
00502
00503 TXC_ASSERT(koa != NULL);
00504 TXC_ASSERT(fd < TXC_KOA_MAP_SIZE);
00505
00506 koamgr = koa->manager;
00507
00508 if (lock) {
00509 TXC_MUTEX_LOCK(&(koamgr->map[fd].mutex));
00510 }
00511 if (koamgr->map[fd].koa == NULL) {
00512 return TXC_R_FAILURE;
00513 }
00514 koamgr->map[fd].koa = NULL;
00515
00516 for (i=0; i<koa->fdref.refcnt; i++) {
00517 if (koa->fdref.fd[i] == fd) {
00518 index = i;
00519 break;
00520 }
00521 }
00522 if (index < 0) {
00523 if (lock) {
00524 TXC_MUTEX_UNLOCK(&(koamgr->map[fd].mutex));
00525 }
00526 return TXC_R_FAILURE;
00527 }
00528 koa->fdref.fd[index] = koa->fdref.fd[koa->fdref.refcnt];
00529 koa->fdref.refcnt--;
00530
00531 koa->refcnt--;
00532 last_detach = (koa->refcnt == 0) ? 1 : 0;
00533 if (last_detach) {
00534
00535 if (koa->type == TXC_KOA_IS_FILE) {
00536 alias_cache_remove(koamgr, koa);
00537 }
00538 txc_koa_destroy(&koa);
00539 }
00540
00541
00542 TXC_DEBUG_PRINT(TXC_DEBUG_KOA,
00543 "txc_koa_detach_fd: koa = %p, fd = %d, refcnt = %d, sentinel = %p\n",
00544 koa, fd, koa->refcnt, koa->sentinel);
00545
00546 if (lock) {
00547 TXC_MUTEX_UNLOCK(&(koamgr->map[fd].mutex));
00548 }
00549
00550 return TXC_R_SUCCESS;
00551 }
00552
00553
00562 txc_result_t
00563 txc_koa_lookup_fd2koa(txc_koamgr_t *koamgr, int fd, txc_koa_t **koap)
00564 {
00565 TXC_ASSERT(fd < TXC_KOA_MAP_SIZE);
00566 *koap = koamgr->map[fd].koa;
00567 if (*koap == NULL) {
00568 return TXC_R_FAILURE;
00569 }
00570 return TXC_R_SUCCESS;
00571 }
00572
00573
00581 txc_result_t
00582 txc_koa_lock_fd(txc_koamgr_t *koamgr, int fd)
00583 {
00584 if (0 == TXC_MUTEX_LOCK(&(koamgr->map[fd].mutex))) {
00585 return TXC_R_SUCCESS;
00586 } else {
00587 return TXC_R_FAILURE;
00588 }
00589 }
00590
00591
00599 txc_result_t
00600 txc_koa_unlock_fd(txc_koamgr_t *koamgr, int fd)
00601 {
00602 if (0 == TXC_MUTEX_UNLOCK(&(koamgr->map[fd].mutex))) {
00603 return TXC_R_SUCCESS;
00604 } else {
00605 return TXC_R_FAILURE;
00606 }
00607 }
00608
00609
00616 txc_result_t
00617 txc_koa_lock_fds_refby_koa(txc_koa_t *koa)
00618 {
00619 int i;
00620 int fd;
00621 txc_fd2koa_t *entry;
00622 txc_koamgr_t *koamgr = koa->manager;
00623
00624
00625
00626
00627
00628
00629
00630 for (i=0; i<koa->fdref.refcnt; i++) {
00631 fd = koa->fdref.fd[i];
00632 entry = &koamgr->map[fd];
00633 TXC_MUTEX_LOCK(&(entry->mutex));
00634 }
00635 return TXC_R_SUCCESS;
00636 }
00637
00638
00645 txc_result_t
00646 txc_koa_unlock_fds_refby_koa(txc_koa_t *koa)
00647 {
00648 int i;
00649 int fd;
00650 txc_fd2koa_t *entry;
00651 txc_koamgr_t *koamgr = koa->manager;
00652
00653 for (i=0; i<koa->fdref.refcnt; i++) {
00654 fd = koa->fdref.fd[i];
00655 entry = &koamgr->map[fd];
00656 TXC_MUTEX_UNLOCK(&(entry->mutex));
00657 }
00658 return TXC_R_SUCCESS;
00659 }
00660
00661
00669 txc_result_t
00670 txc_koa_path2inode(const char *path, ino_t *inode_number)
00671 {
00672 int ret;
00673 struct stat stat_buf;
00674
00675 ret = txc_libc_stat(path, &stat_buf);
00676 if (ret==0) {
00677 *inode_number = stat_buf.st_ino;
00678 } else {
00679 *inode_number = (ino_t) 0;
00680 }
00681
00682 return TXC_R_SUCCESS;
00683 }
00684
00685
00695 txc_result_t
00696 txc_koa_attach(txc_koa_t *koa)
00697 {
00698 int first_attach;
00699 txc_koamgr_t *koamgr;
00700
00701 TXC_ASSERT(koa != NULL);
00702
00703 koamgr = koa->manager;
00704 TXC_MUTEX_LOCK(&(koa->mutex));
00705 koa->refcnt++;
00706 first_attach = (koa->refcnt == 1) ? 1 : 0;
00707 if (first_attach) {
00712 if (koa->type == TXC_KOA_IS_FILE) {
00713 alias_cache_insert(koamgr, koa);
00714 }
00715 }
00716
00717 TXC_DEBUG_PRINT(TXC_DEBUG_KOA,
00718 "txc_koa_attach: koa = %p, refcnt = %d, sentinel = %p\n",
00719 koa, koa->refcnt, koa->sentinel);
00720 TXC_MUTEX_UNLOCK(&(koa->mutex));
00721
00722 return TXC_R_SUCCESS;
00723 }
00724
00725
00736 txc_result_t
00737 txc_koa_detach(txc_koa_t *koa)
00738 {
00739 int last_detach;
00740 txc_koamgr_t *koamgr;
00741
00742 TXC_ASSERT(koa != NULL);
00743
00744 koamgr = koa->manager;
00745 TXC_MUTEX_LOCK(&(koa->mutex));
00746 koa->refcnt--;
00747 last_detach = (koa->refcnt == 0) ? 1 : 0;
00748 if (last_detach) {
00750 if (koa->type == TXC_KOA_IS_FILE) {
00751 alias_cache_remove(koamgr, koa);
00752 }
00753 txc_koa_destroy(&koa);
00754 }
00755
00756 TXC_DEBUG_PRINT(TXC_DEBUG_KOA,
00757 "txc_koa_detach: koa = %p, refcnt = %d, sentinel = %p\n",
00758 koa, koa->refcnt, koa->sentinel);
00759 TXC_MUTEX_UNLOCK(&(koa->mutex));
00760
00761 return TXC_R_SUCCESS;
00762 }
00763
00764
00771 txc_sentinel_t *
00772 txc_koa_get_sentinel(txc_koa_t *koa)
00773 {
00774 return koa->sentinel;
00775 }
00776
00777
00784 txc_koamgr_t *
00785 txc_koa_get_koamgr(txc_koa_t *koa)
00786 {
00787 return koa->manager;
00788 }
00789
00790
00797 void *
00798 txc_koa_get_buffer(txc_koa_t *koa)
00799 {
00800 void *ret;
00801
00802 switch (koa->type) {
00803 case TXC_KOA_IS_SOCK_DGRAM:
00804 ret = (void *) koa->sock_dgram.buffer_circular_input;
00805 case TXC_KOA_IS_PIPE_READ_END:
00806 ret = (void *) koa->pipe_read_end.buffer_circular_input;
00807 }
00808 return ret;
00809 }