Overview
Comment: | Tweaked hashing algorithm, added destructor for threads so that as threads terminate they are cleaned up |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | 770584ac09a823c45b6bd0db3a097e8dc959045c |
User & Date: | rkeene on 2014-11-14 04:05:14 |
Other Links: | manifest | tags |
Context
2014-11-14
| ||
04:05 | Updated to have a release and debug CFLAGS check-in: 9cc13bbc4c user: rkeene tags: trunk | |
04:05 | Tweaked hashing algorithm, added destructor for threads so that as threads terminate they are cleaned up check-in: 770584ac09 user: rkeene tags: trunk | |
2014-11-12
| ||
15:23 | Updated to fetch/update host index before fetching manifest check-in: d6262bea99 user: rkeene tags: trunk | |
Changes
Modified appfsd.c from [e49bb6021f] to [6216c87bde].
1 1 #define FUSE_USE_VERSION 26 2 2 3 3 #include <sys/fsuid.h> 4 4 #include <sys/types.h> 5 5 #include <pthread.h> 6 6 #include <signal.h> 7 +#include <limits.h> 7 8 #include <string.h> 8 9 #include <stdarg.h> 9 10 #include <stdlib.h> 10 11 #include <unistd.h> 11 12 #include <errno.h> 12 13 #include <fcntl.h> 13 14 #include <stdio.h> ................................................................................ 117 118 118 119 if (error_string) { 119 120 *error_string = strdup("Unable to create Tcl interpreter."); 120 121 } 121 122 122 123 return(NULL); 123 124 } 125 + 126 + Tcl_Preserve(interp); 124 127 125 128 tcl_ret = Tcl_Init(interp); 126 129 if (tcl_ret != TCL_OK) { 127 130 fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); 128 131 fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 129 132 130 133 if (error_string) { 131 134 *error_string = strdup(Tcl_GetStringResult(interp)); 132 135 } 133 136 137 + Tcl_Release(interp); 138 + 139 + APPFS_DEBUG("Terminating Tcl interpreter."); 140 + 134 141 Tcl_DeleteInterp(interp); 135 142 136 143 return(NULL); 137 144 } 138 145 139 146 tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]"); 140 147 if (tcl_ret != TCL_OK) { ................................................................................ 141 148 fprintf(stderr, "Unable to initialize Tcl SHA1. Aborting.\n"); 142 149 fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 143 150 144 151 if (error_string) { 145 152 *error_string = strdup(Tcl_GetStringResult(interp)); 146 153 } 147 154 155 + Tcl_Release(interp); 156 + 157 + APPFS_DEBUG("Terminating Tcl interpreter."); 158 + 148 159 Tcl_DeleteInterp(interp); 149 160 150 161 return(NULL); 151 162 } 152 163 153 164 tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]"); 154 165 if (tcl_ret != TCL_OK) { ................................................................................ 155 166 fprintf(stderr, "Unable to initialize Tcl AppFS Package. Aborting.\n"); 156 167 fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 157 168 158 169 if (error_string) { 159 170 *error_string = strdup(Tcl_GetStringResult(interp)); 160 171 } 161 172 173 + Tcl_Release(interp); 174 + 175 + APPFS_DEBUG("Terminating Tcl interpreter."); 176 + 162 177 Tcl_DeleteInterp(interp); 163 178 164 179 return(NULL); 165 180 } 166 181 167 182 /* 168 183 * Load "pki.tcl" in the same way as appfsd.tcl (see below) ................................................................................ 174 189 fprintf(stderr, "Unable to initialize Tcl PKI. Aborting.\n"); 175 190 fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 176 191 177 192 if (error_string) { 178 193 *error_string = strdup(Tcl_GetStringResult(interp)); 179 194 } 180 195 196 + Tcl_Release(interp); 197 + 198 + APPFS_DEBUG("Terminating Tcl interpreter."); 199 + 181 200 Tcl_DeleteInterp(interp); 182 201 183 202 return(NULL); 184 203 } 185 204 186 205 /* 187 206 * Load the "appfsd.tcl" script, which is "compiled" into a C header ................................................................................ 195 214 fprintf(stderr, "Unable to initialize Tcl AppFS script. Aborting.\n"); 196 215 fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 197 216 198 217 if (error_string) { 199 218 *error_string = strdup(Tcl_GetStringResult(interp)); 200 219 } 201 220 221 + Tcl_Release(interp); 222 + 223 + APPFS_DEBUG("Terminating Tcl interpreter."); 224 + 202 225 Tcl_DeleteInterp(interp); 203 226 204 227 return(NULL); 205 228 } 206 229 207 230 /* 208 231 * Set global variables from C to Tcl ................................................................................ 210 233 if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) { 211 234 fprintf(stderr, "Unable to set cache directory. This should never fail.\n"); 212 235 213 236 if (error_string) { 214 237 *error_string = strdup(Tcl_GetStringResult(interp)); 215 238 } 216 239 240 + Tcl_Release(interp); 241 + 242 + APPFS_DEBUG("Terminating Tcl interpreter."); 243 + 217 244 Tcl_DeleteInterp(interp); 218 245 219 246 return(NULL); 220 247 } 221 248 222 249 /* 223 250 * Initialize the "appfsd.tcl" environment, which must be done after ................................................................................ 228 255 fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init). Aborting.\n"); 229 256 fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); 230 257 231 258 if (error_string) { 232 259 *error_string = strdup(Tcl_GetStringResult(interp)); 233 260 } 234 261 262 + Tcl_Release(interp); 263 + 264 + APPFS_DEBUG("Terminating Tcl interpreter."); 265 + 235 266 Tcl_DeleteInterp(interp); 236 267 237 268 return(NULL); 238 269 } 239 270 240 271 /* 241 272 * Hide some Tcl commands that we do not care to use and which may 242 273 * slow down run-time operations. 243 274 */ 244 275 Tcl_HideCommand(interp, "auto_load_index", "auto_load_index"); 245 276 Tcl_HideCommand(interp, "unknown", "unknown"); 277 + Tcl_HideCommand(interp, "exit", "exit"); 278 + 279 + /* 280 + * Release the hold we have on the interpreter so that it may be 281 + * deleted if needed 282 + */ 283 + Tcl_Release(interp); 246 284 247 285 /* 248 286 * Return the completely initialized interpreter 249 287 */ 250 288 return(interp); 251 289 } 252 290 ................................................................................ 265 303 if (interp != NULL && thread_interp_reset_key != global_interp_reset_key) { 266 304 APPFS_DEBUG("Terminating old interpreter and restarting due to reset request."); 267 305 268 306 Tcl_DeleteInterp(interp); 269 307 270 308 interp = NULL; 271 309 272 - thread_interp_reset_key = global_interp_reset_key; 310 + pthread_ret = pthread_setspecific(interpKey, interp); 273 311 } 312 + 313 + thread_interp_reset_key = global_interp_reset_key; 274 314 275 315 if (interp == NULL) { 276 316 interp = appfs_create_TclInterp(NULL); 277 317 278 318 if (interp == NULL) { 279 319 return(NULL); 280 320 } 281 321 282 322 pthread_ret = pthread_setspecific(interpKey, interp); 283 323 if (pthread_ret != 0) { 324 + APPFS_DEBUG("pthread_setspecific() failed. Terminating Tcl interpreter."); 325 + 284 326 Tcl_DeleteInterp(interp); 285 327 286 328 return(NULL); 287 329 } 288 330 } 289 331 290 332 return(interp); ................................................................................ 451 493 } 452 494 453 495 /* 454 496 * Generate an inode for a given path. The inode should be computed in such 455 497 * a way that it is unlikely to be duplicated and remains the same for a given 456 498 * file 457 499 */ 500 +#if UINT_MAX < 4294967295 501 +#error Integer size is too small 502 +#endif 458 503 static long long appfs_get_path_inode(const char *path) { 459 - long long retval; 504 + int retval; 460 505 const char *p; 461 506 462 507 retval = 10; 463 508 464 509 for (p = path; *p; p++) { 465 510 retval %= 4290960290ULL; 466 511 retval += *p; 467 - retval <<= 7; 512 + retval <<= 6; 468 513 } 469 514 470 515 retval += 10; 471 - retval %= 4294967296ULL; 516 + retval %= 4294967286ULL; 517 + retval += 10; 472 518 473 519 return(retval); 474 520 } 475 521 476 522 /* 477 523 * Cache Get Path Info lookups for speed 478 524 */ ................................................................................ 640 686 Tcl_Obj *attrs_dict, *attr_value; 641 687 const char *attr_value_str; 642 688 Tcl_WideInt attr_value_wide; 643 689 int attr_value_int; 644 690 static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL, *attr_key_packaged = NULL; 645 691 int cache_ret; 646 692 int tcl_ret; 693 + uid_t fsuid; 647 694 648 - cache_ret = appfs_get_path_info_cache_get(path, appfs_get_fsuid(), pathinfo); 695 + fsuid = appfs_get_fsuid(); 696 + 697 + cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo); 649 698 if (cache_ret == 0) { 650 699 if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) { 651 700 return(-ENOENT); 652 701 } 653 702 654 703 if (pathinfo->type == APPFS_PATHTYPE_INVALID) { 655 704 return(-EIO); ................................................................................ 668 717 tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); 669 718 if (tcl_ret != TCL_OK) { 670 719 APPFS_DEBUG("::appfs::getattr(%s) failed.", path); 671 720 APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp)); 672 721 673 722 pathinfo->type = APPFS_PATHTYPE_DOES_NOT_EXIST; 674 723 675 - appfs_get_path_info_cache_add(path, appfs_get_fsuid(), pathinfo); 724 + appfs_get_path_info_cache_add(path, fsuid, pathinfo); 676 725 677 726 Tcl_Release(interp); 678 727 679 728 return(-ENOENT); 680 729 } 681 730 682 731 if (attr_key_type == NULL) { ................................................................................ 787 836 } 788 837 } else { 789 838 pathinfo->time = 0; 790 839 } 791 840 792 841 Tcl_Release(interp); 793 842 794 - appfs_get_path_info_cache_add(path, appfs_get_fsuid(), pathinfo); 843 + appfs_get_path_info_cache_add(path, fsuid, pathinfo); 795 844 796 845 return(0); 797 846 } 798 847 799 848 static char *appfs_prepare_to_create(const char *path) { 800 849 Tcl_Interp *interp; 801 850 const char *real_path; ................................................................................ 1541 1590 /* Request to perform a "hot" restart */ 1542 1591 if (sig == SIGHUP) { 1543 1592 appfs_hot_restart(); 1544 1593 } 1545 1594 1546 1595 return; 1547 1596 } 1597 + 1598 +/* 1599 + * Terminate a thread 1600 + */ 1601 +static void appfs_terminate_interp(void *_interp) { 1602 + Tcl_Interp *interp; 1603 + 1604 + APPFS_DEBUG("Called: _interp = %p", _interp); 1605 + 1606 + if (_interp == NULL) { 1607 + APPFS_DEBUG("Terminating thread with no interpreter"); 1608 + 1609 + return; 1610 + } 1611 + 1612 + interp = _interp; 1613 + 1614 + APPFS_DEBUG("Terminating interpreter due to thread termination"); 1615 + 1616 + Tcl_DeleteInterp(interp); 1617 + 1618 + return; 1619 +} 1548 1620 1549 1621 /* 1550 1622 * FUSE operations structure 1551 1623 */ 1552 1624 static struct fuse_operations appfs_operations = { 1553 1625 .getattr = appfs_fuse_getattr, 1554 1626 .readdir = appfs_fuse_readdir, ................................................................................ 1622 1694 Tcl_StaticPackage(NULL, "appfsd", Appfsd_Init, NULL); 1623 1695 1624 1696 /* 1625 1697 * Create a thread-specific-data (TSD) key for each thread to refer 1626 1698 * to its own Tcl interpreter. Tcl interpreters must be unique per 1627 1699 * thread and new threads are dynamically created by FUSE. 1628 1700 */ 1629 - pthread_ret = pthread_key_create(&interpKey, NULL); 1701 + pthread_ret = pthread_key_create(&interpKey, appfs_terminate_interp); 1630 1702 if (pthread_ret != 0) { 1631 1703 fprintf(stderr, "Unable to create TSD key for Tcl. Aborting.\n"); 1632 1704 1633 1705 return(1); 1634 1706 } 1635 1707 1636 1708 /*