src/core/koa.c

Go to the documentation of this file.
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;                  /* mutex */
00135         txc_hash_table_t *hash_tbl;              /* hash table */
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         /* Precreate standard KOAs: input, output, error */
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; /* do nothing */
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          * txc_sentinel_detach will destroy the sentinel if after the
00416          * detach operation is (sentinel->refcnt == 0) 
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; /* do nothing */
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         /* Remove backward pointer from KOA to file descriptor */
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                 /* Last detach -- remove it from the alias cache if aliasable KOA. */
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          * FIXME: Is the following still true ???
00626          *
00627          * This is the only point where we acquire multiple FD locks.
00628          * Therefore we don't need to acquire locks in some total order. 
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 }

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7