ddispatch.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "ncdispatch.h"
  2. #include "nc_uri.h"
  3. extern int NCSUBSTRATE_intialize(void);
  4. /* Define vectors of zeros and ones for use with various nc_get_varX function*/
  5. size_t nc_sizevector0[NC_MAX_DIMS];
  6. size_t nc_sizevector1[NC_MAX_DIMS];
  7. ptrdiff_t nc_ptrdiffvector1[NC_MAX_DIMS];
  8. /* Define the known protocols and their manipulations */
  9. static struct NCPROTOCOLLIST {
  10. char* protocol;
  11. char* substitute;
  12. int modelflags;
  13. } ncprotolist[] = {
  14. {"http",NULL,0},
  15. {"https",NULL,0},
  16. {"file",NULL,NC_DISPATCH_NCD},
  17. {"dods","http",NC_DISPATCH_NCD},
  18. {"dodss","https",NC_DISPATCH_NCD},
  19. {"cdmr","http",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
  20. {"cdmrs","https",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
  21. {"cdmremote","http",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
  22. {"cdmremotes","https",NC_DISPATCH_NCR|NC_DISPATCH_NC4},
  23. {NULL,NULL,0} /* Terminate search */
  24. };
  25. /* Define the server to ping in order;
  26. make the order attempt to optimize
  27. against future changes.
  28. */
  29. static const char* servers[] = {
  30. "http://motherlode.ucar.edu:8081", /* try this first */
  31. "http://remotetest.unidata.ucar.edu",
  32. "http://remotetest.ucar.edu",
  33. "http://motherlode.ucar.edu:8080",
  34. "http://motherlode.ucar.edu",
  35. "http://remotetests.unidata.ucar.edu",
  36. "http://remotetests.ucar.edu",
  37. NULL
  38. };
  39. /*
  40. static nc_type longtype = (sizeof(long) == sizeof(int)?NC_INT:NC_INT64);
  41. static nc_type ulongtype = (sizeof(unsigned long) == sizeof(unsigned int)?NC_UINT:NC_UINT64);
  42. */
  43. /* Allow dispatch to do initialization */
  44. int
  45. NCDISPATCH_initialize(void)
  46. {
  47. extern int NCSUBSTRATE_initialize(void);
  48. int i;
  49. NCSUBSTRATE_initialize();
  50. for(i=0;i<NC_MAX_VAR_DIMS;i++) {
  51. nc_sizevector0[i] = 0;
  52. nc_sizevector1[i] = 1;
  53. nc_ptrdiffvector1[i] = 1;
  54. }
  55. return NC_NOERR;
  56. }
  57. /* search list of servers and return first that succeeds when
  58. concatenated with the specified path part
  59. */
  60. const char*
  61. NC_findtestserver(const char* path)
  62. {
  63. #ifdef USE_DAP
  64. /* NCDAP_ping is defined in libdap2/ncdap3.c */
  65. const char** svc;
  66. if(path == NULL) path = "";
  67. for(svc=servers;*svc != NULL;svc++) {
  68. int stat;
  69. char url[4096];
  70. snprintf(url,sizeof(url),"%s%s%s",
  71. *svc,
  72. (path[0] == '/' ? "" : "/"),
  73. path);
  74. stat = NCDAP_ping(url);
  75. if(stat == NC_NOERR)
  76. return *svc;
  77. }
  78. #endif
  79. return NULL;
  80. }
  81. /* return 1 if path looks like a url; 0 otherwise */
  82. int
  83. NC_testurl(const char* path)
  84. {
  85. int isurl = 0;
  86. NC_URI* tmpurl = NULL;
  87. char* p;
  88. if(path == NULL) return 0;
  89. /* find leading non-blank */
  90. for(p=(char*)path;*p;p++) {if(*p != ' ') break;}
  91. /* Do some initial checking to see if this looks like a file path */
  92. if(*p == '/') return 0; /* probably an absolute file path */
  93. /* Ok, try to parse as a url */
  94. if(nc_uriparse(path,&tmpurl)) {
  95. /* Do some extra testing to make sure this really is a url */
  96. /* Look for a knownprotocol */
  97. struct NCPROTOCOLLIST* protolist;
  98. for(protolist=ncprotolist;protolist->protocol;protolist++) {
  99. if(strcmp(tmpurl->protocol,protolist->protocol) == 0) {
  100. isurl=1;
  101. break;
  102. }
  103. }
  104. nc_urifree(tmpurl);
  105. return isurl;
  106. }
  107. return 0;
  108. }
  109. /*
  110. Return the OR of some of the NC_DISPATCH flags
  111. Assumes that the path is known to be a url
  112. */
  113. int
  114. NC_urlmodel(const char* path)
  115. {
  116. int model = 0;
  117. NC_URI* tmpurl = NULL;
  118. struct NCPROTOCOLLIST* protolist;
  119. if(!nc_uriparse(path,&tmpurl)) goto done;
  120. /* Look at any prefixed parameters */
  121. if(nc_urilookup(tmpurl,"netcdf4",NULL)
  122. || nc_urilookup(tmpurl,"netcdf-4",NULL)) {
  123. model = (NC_DISPATCH_NC4|NC_DISPATCH_NCD);
  124. } else if(nc_urilookup(tmpurl,"netcdf3",NULL)
  125. || nc_urilookup(tmpurl,"netcdf-3",NULL)) {
  126. model = (NC_DISPATCH_NC3|NC_DISPATCH_NCD);
  127. } else if(nc_urilookup(tmpurl,"cdmremote",NULL)
  128. || nc_urilookup(tmpurl,"cdmr",NULL)) {
  129. model = (NC_DISPATCH_NCR|NC_DISPATCH_NC4);
  130. }
  131. if(model == 0) {
  132. /* Now look at the protocol */
  133. for(protolist=ncprotolist;protolist->protocol;protolist++) {
  134. if(strcmp(tmpurl->protocol,protolist->protocol) == 0) {
  135. model |= protolist->modelflags;
  136. if(protolist->substitute) {
  137. if(tmpurl->protocol) free(tmpurl->protocol);
  138. tmpurl->protocol = strdup(protolist->substitute);
  139. }
  140. break;
  141. }
  142. }
  143. }
  144. /* Force NC_DISPATCH_NC3 if necessary */
  145. if((model & NC_DISPATCH_NC4) == 0)
  146. model |= (NC_DISPATCH_NC3 | NC_DISPATCH_NCD);
  147. done:
  148. nc_urifree(tmpurl);
  149. return model;
  150. }
  151. /* Override dispatch table management */
  152. static NC_Dispatch* NC_dispatch_override = NULL;
  153. /* Override dispatch table management */
  154. NC_Dispatch*
  155. NC_get_dispatch_override(void) {
  156. return NC_dispatch_override;
  157. }
  158. void NC_set_dispatch_override(NC_Dispatch* d)
  159. {
  160. NC_dispatch_override = d;
  161. }
  162. /* Overlay by treating the tables as arrays of void*.
  163. Overlay rules are:
  164. overlay base merge
  165. ------- ---- -----
  166. null null null
  167. null y y
  168. x null x
  169. x y x
  170. */
  171. int
  172. NC_dispatch_overlay(const NC_Dispatch* overlay, const NC_Dispatch* base, NC_Dispatch* merge)
  173. {
  174. void** voverlay = (void**)overlay;
  175. void** vmerge;
  176. int i, count = sizeof(NC_Dispatch) / sizeof(void*);
  177. /* dispatch table must be exact multiple of sizeof(void*) */
  178. assert(count * sizeof(void*) == sizeof(NC_Dispatch));
  179. *merge = *base;
  180. vmerge = (void**)merge;
  181. for(i=0;i<count;i++) {
  182. if(voverlay[i] == NULL) continue;
  183. vmerge[i] = voverlay[i];
  184. }
  185. /* Finally, the merge model should always be the overlay model */
  186. merge->model = overlay->model;
  187. return NC_NOERR;
  188. }