/[jscoverage]/trunk/jscoverage-server.c
ViewVC logotype

Diff of /trunk/jscoverage-server.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 116 by siliconforks, Sat May 31 21:42:36 2008 UTC revision 146 by siliconforks, Thu Jun 19 19:33:05 2008 UTC
# Line 25  Line 25 
25  #include <string.h>  #include <string.h>
26    
27  #include <dirent.h>  #include <dirent.h>
28    #ifdef HAVE_PTHREAD_H
29  #include <pthread.h>  #include <pthread.h>
30    #endif
31    
32  #include "http-server.h"  #include "http-server.h"
33  #include "instrument-js.h"  #include "instrument-js.h"
# Line 64  Line 66 
66  static const char ** no_instrument;  static const char ** no_instrument;
67  static size_t num_no_instrument = 0;  static size_t num_no_instrument = 0;
68    
69    #ifdef __MINGW32__
70    CRITICAL_SECTION javascript_mutex;
71    CRITICAL_SECTION source_cache_mutex;
72    #define LOCK EnterCriticalSection
73    #define UNLOCK LeaveCriticalSection
74    #else
75  pthread_mutex_t javascript_mutex = PTHREAD_MUTEX_INITIALIZER;  pthread_mutex_t javascript_mutex = PTHREAD_MUTEX_INITIALIZER;
76  pthread_mutex_t source_cache_mutex = PTHREAD_MUTEX_INITIALIZER;  pthread_mutex_t source_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
77    #define LOCK pthread_mutex_lock
78    #define UNLOCK pthread_mutex_unlock
79    #endif
80    
81  static Stream * find_cached_source(const char * url) {  static Stream * find_cached_source(const char * url) {
82    Stream * result = NULL;    Stream * result = NULL;
83    pthread_mutex_lock(&source_cache_mutex);    LOCK(&source_cache_mutex);
84    for (SourceCache * p = source_cache; p != NULL; p = p->next) {    for (SourceCache * p = source_cache; p != NULL; p = p->next) {
85      if (strcmp(url, p->url) == 0) {      if (strcmp(url, p->url) == 0) {
86        result = p->source;        result = p->source;
87        break;        break;
88      }      }
89    }    }
90    pthread_mutex_unlock(&source_cache_mutex);    UNLOCK(&source_cache_mutex);
91    return result;    return result;
92  }  }
93    
# Line 84  Line 95 
95    SourceCache * new_source_cache = xmalloc(sizeof(SourceCache));    SourceCache * new_source_cache = xmalloc(sizeof(SourceCache));
96    new_source_cache->url = xstrdup(url);    new_source_cache->url = xstrdup(url);
97    new_source_cache->source = source;    new_source_cache->source = source;
98    pthread_mutex_lock(&source_cache_mutex);    LOCK(&source_cache_mutex);
99    new_source_cache->next = source_cache;    new_source_cache->next = source_cache;
100    source_cache = new_source_cache;    source_cache = new_source_cache;
101    pthread_mutex_unlock(&source_cache_mutex);    UNLOCK(&source_cache_mutex);
102  }  }
103    
104  static int get(const char * url, Stream * stream) __attribute__((warn_unused_result));  static int get(const char * url, Stream * stream) __attribute__((warn_unused_result));
# Line 338  Line 349 
349    return true;    return true;
350  }  }
351    
352  static int merge(Coverage * coverage, const char * path, size_t size) __attribute__((warn_unused_result));  static int merge(Coverage * coverage, FILE * f) __attribute__((warn_unused_result));
353    
354  static int merge(Coverage * coverage, const char * path, size_t size) {  static int merge(Coverage * coverage, FILE * f) {
355    FILE * f = fopen(path, "r");    Stream * stream = Stream_new(0);
356    if (f == NULL) {    Stream_write_file_contents(stream, f);
     return -1;  
   }  
   uint8_t * buffer = xmalloc(size);  
   if (fread(buffer, 1, size, f) != size) {  
     fclose(f);  
     free(buffer);  
     return -1;  
   }  
   fclose(f);  
357    
358    pthread_mutex_lock(&javascript_mutex);    LOCK(&javascript_mutex);
359    int result = jscoverage_parse_json(coverage, buffer, size);    int result = jscoverage_parse_json(coverage, stream->data, stream->length);
360    pthread_mutex_unlock(&javascript_mutex);    UNLOCK(&javascript_mutex);
361    
362    free(buffer);    Stream_delete(stream);
363    return result;    return result;
364  }  }
365    
# Line 444  Line 446 
446        /* check that the path begins with / */        /* check that the path begins with / */
447        if (file_coverage->id[0] == '/') {        if (file_coverage->id[0] == '/') {
448          char * source_path = make_path(document_root, file_coverage->id + 1);          char * source_path = make_path(document_root, file_coverage->id + 1);
449          FILE * source_file = fopen(source_path, "r");          FILE * source_file = fopen(source_path, "rb");
450          free(source_path);          free(source_path);
451          if (source_file == NULL) {          if (source_file == NULL) {
452            fputs("\"\"", f);            fputs("\"\"", f);
# Line 511  Line 513 
513      }      }
514    
515      Coverage * coverage = Coverage_new();      Coverage * coverage = Coverage_new();
516      pthread_mutex_lock(&javascript_mutex);      LOCK(&javascript_mutex);
517      int result = jscoverage_parse_json(coverage, json->data, json->length);      int result = jscoverage_parse_json(coverage, json->data, json->length);
518      pthread_mutex_unlock(&javascript_mutex);      UNLOCK(&javascript_mutex);
519      Stream_delete(json);      Stream_delete(json);
520    
521      if (result != 0) {      if (result != 0) {
# Line 524  Line 526 
526    
527      mkdir_if_necessary(report_directory);      mkdir_if_necessary(report_directory);
528      char * path = make_path(report_directory, "jscoverage.json");      char * path = make_path(report_directory, "jscoverage.json");
529    
530        /* check if the JSON file exists */
531      struct stat buf;      struct stat buf;
532      if (stat(path, &buf) == 0) {      if (stat(path, &buf) == 0) {
533        /* it exists: merge */        /* it exists: merge */
534        result = merge(coverage, path, buf.st_size);        FILE * f = fopen(path, "r");
535          if (f == NULL) {
536            result = 1;
537          }
538          else {
539            result = merge(coverage, f);
540            if (fclose(f) == EOF) {
541              result = 1;
542            }
543          }
544        if (result != 0) {        if (result != 0) {
545          free(path);          free(path);
546          Coverage_delete(coverage);          Coverage_delete(coverage);
# Line 604  Line 617 
617  }  }
618    
619  static void instrument_js(const char * id, Stream * input_stream, Stream * output_stream) {  static void instrument_js(const char * id, Stream * input_stream, Stream * output_stream) {
620    pthread_mutex_lock(&javascript_mutex);    LOCK(&javascript_mutex);
621    jscoverage_instrument_js(id, input_stream, output_stream);    jscoverage_instrument_js(id, input_stream, output_stream);
622    pthread_mutex_unlock(&javascript_mutex);    UNLOCK(&javascript_mutex);
623    
624    const struct Resource * resource = get_resource("report.js");    const struct Resource * resource = get_resource("report.js");
625    Stream_write(output_stream, resource->data, resource->length);    Stream_write(output_stream, resource->data, resource->length);
# Line 814  Line 827 
827    }    }
828    
829    filesystem_path = make_path(document_root, abs_path + 1);    filesystem_path = make_path(document_root, abs_path + 1);
830      size_t filesystem_path_length = strlen(filesystem_path);
831      if (filesystem_path_length > 0 && filesystem_path[filesystem_path_length - 1] == '/') {
832        /* stat on Windows doesn't work with trailing slash */
833        filesystem_path[filesystem_path_length - 1] = '\0';
834      }
835    
836    struct stat buf;    struct stat buf;
837    if (stat(filesystem_path, &buf) == -1) {    if (stat(filesystem_path, &buf) == -1) {
# Line 822  Line 840 
840    }    }
841    
842    if (S_ISDIR(buf.st_mode)) {    if (S_ISDIR(buf.st_mode)) {
843      if (filesystem_path[strlen(filesystem_path) - 1] != '/') {      if (abs_path[strlen(abs_path) - 1] != '/') {
844        const char * request_uri = HTTPExchange_get_request_uri(exchange);        const char * request_uri = HTTPExchange_get_request_uri(exchange);
845        char * uri = xmalloc(strlen(request_uri) + 2);        char * uri = xmalloc(strlen(request_uri) + 2);
846        strcpy(uri, request_uri);        strcpy(uri, request_uri);
# Line 857  Line 875 
875      closedir(d);      closedir(d);
876    }    }
877    else if (S_ISREG(buf.st_mode)) {    else if (S_ISREG(buf.st_mode)) {
878      FILE * f = fopen(filesystem_path, "r");      FILE * f = fopen(filesystem_path, "rb");
879      if (f == NULL) {      if (f == NULL) {
880        send_response(exchange, 404, "Not found\n");        send_response(exchange, 404, "Not found\n");
881        goto done;        goto done;
# Line 865  Line 883 
883    
884      const char * content_type = get_content_type(filesystem_path);      const char * content_type = get_content_type(filesystem_path);
885      HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, content_type);      HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, content_type);
886      const char * request_uri = HTTPExchange_get_request_uri(exchange);      if (strcmp(content_type, "text/javascript") == 0 && ! is_no_instrument(abs_path)) {
     if (strcmp(content_type, "text/javascript") == 0 && ! is_no_instrument(request_uri)) {  
887        Stream * input_stream = Stream_new(0);        Stream * input_stream = Stream_new(0);
888        Stream * output_stream = Stream_new(0);        Stream * output_stream = Stream_new(0);
889    
890        Stream_write_file_contents(input_stream, f);        Stream_write_file_contents(input_stream, f);
891    
892        instrument_js(request_uri, input_stream, output_stream);        instrument_js(abs_path, input_stream, output_stream);
893    
894        if (HTTPExchange_write_response(exchange, output_stream->data, output_stream->length) != 0) {        if (HTTPExchange_write_response(exchange, output_stream->data, output_stream->length) != 0) {
895          HTTPServer_log_err("Warning: error writing to client\n");          HTTPServer_log_err("Warning: error writing to client\n");
# Line 1021  Line 1038 
1038    
1039    /* is this a shutdown? */    /* is this a shutdown? */
1040    if (shutdown) {    if (shutdown) {
1041    #ifdef __MINGW32__
1042        WSADATA data;
1043        if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
1044          fatal("could not start Winsock");
1045        }
1046    #endif
1047    
1048      /* INADDR_LOOPBACK */      /* INADDR_LOOPBACK */
1049      HTTPConnection * connection = HTTPConnection_new_client("127.0.0.1", numeric_port);      HTTPConnection * connection = HTTPConnection_new_client("127.0.0.1", numeric_port);
1050      if (connection == NULL) {      if (connection == NULL) {
# Line 1050  Line 1074 
1074    
1075    jscoverage_init();    jscoverage_init();
1076    
1077    #ifndef __MINGW32__
1078    /* handle broken pipe */    /* handle broken pipe */
1079    signal(SIGPIPE, SIG_IGN);    signal(SIGPIPE, SIG_IGN);
1080    #endif
1081    
1082    #ifdef __MINGW32__
1083    InitializeCriticalSection(&javascript_mutex);
1084    InitializeCriticalSection(&source_cache_mutex);
1085    #endif
1086    
1087    if (verbose) {    if (verbose) {
1088      printf("Starting HTTP server on %s:%lu\n", ip_address, numeric_port);      printf("Starting HTTP server on %s:%lu\n", ip_address, numeric_port);
1089        fflush(stdout);
1090    }    }
1091    HTTPServer_run(ip_address, (uint16_t) numeric_port, handler);    HTTPServer_run(ip_address, (uint16_t) numeric_port, handler);
1092    if (verbose) {    if (verbose) {
1093      printf("Stopping HTTP server\n");      printf("Stopping HTTP server\n");
1094        fflush(stdout);
1095    }    }
1096    
1097    jscoverage_cleanup();    jscoverage_cleanup();
1098    
1099    free(no_instrument);    free(no_instrument);
1100    
1101    pthread_mutex_lock(&source_cache_mutex);    LOCK(&source_cache_mutex);
1102    while (source_cache != NULL) {    while (source_cache != NULL) {
1103      SourceCache * p = source_cache;      SourceCache * p = source_cache;
1104      source_cache = source_cache->next;      source_cache = source_cache->next;
# Line 1073  Line 1106 
1106      Stream_delete(p->source);      Stream_delete(p->source);
1107      free(p);      free(p);
1108    }    }
1109    pthread_mutex_unlock(&source_cache_mutex);    UNLOCK(&source_cache_mutex);
1110    
1111    return 0;    return 0;
1112  }  }

Legend:
Removed from v.116  
changed lines
  Added in v.146

  ViewVC Help
Powered by ViewVC 1.1.24