skynet_module.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "skynet.h"
  2. #include "skynet_module.h"
  3. #include "spinlock.h"
  4. #include <assert.h>
  5. #include <string.h>
  6. #include <dlfcn.h>
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <stdio.h>
  10. #define MAX_MODULE_TYPE 32
  11. struct modules {
  12. int count;
  13. struct spinlock lock;
  14. const char * path;
  15. struct skynet_module m[MAX_MODULE_TYPE];
  16. };
  17. static struct modules * M = NULL;
  18. static void *
  19. _try_open(struct modules *m, const char * name) {
  20. const char *l;
  21. const char * path = m->path;
  22. size_t path_size = strlen(path);
  23. size_t name_size = strlen(name);
  24. int sz = path_size + name_size;
  25. //search path
  26. void * dl = NULL;
  27. char tmp[sz];
  28. do
  29. {
  30. memset(tmp,0,sz);
  31. while (*path == ';') path++;
  32. if (*path == '\0') break;
  33. l = strchr(path, ';');
  34. if (l == NULL) l = path + strlen(path);
  35. int len = l - path;
  36. int i;
  37. for (i=0;path[i]!='?' && i < len ;i++) {
  38. tmp[i] = path[i];
  39. }
  40. memcpy(tmp+i,name,name_size);
  41. if (path[i] == '?') {
  42. strncpy(tmp+i+name_size,path+i+1,len - i - 1);
  43. } else {
  44. fprintf(stderr,"Invalid C service path\n");
  45. exit(1);
  46. }
  47. dl = dlopen(tmp, RTLD_NOW | RTLD_GLOBAL);
  48. path = l;
  49. }while(dl == NULL);
  50. if (dl == NULL) {
  51. fprintf(stderr, "try open %s failed : %s\n",name,dlerror());
  52. }
  53. return dl;
  54. }
  55. static struct skynet_module *
  56. _query(const char * name) {
  57. int i;
  58. for (i=0;i<M->count;i++) {
  59. if (strcmp(M->m[i].name,name)==0) {
  60. return &M->m[i];
  61. }
  62. }
  63. return NULL;
  64. }
  65. static void *
  66. get_api(struct skynet_module *mod, const char *api_name) {
  67. size_t name_size = strlen(mod->name);
  68. size_t api_size = strlen(api_name);
  69. char tmp[name_size + api_size + 1];
  70. memcpy(tmp, mod->name, name_size);
  71. memcpy(tmp+name_size, api_name, api_size+1);
  72. char *ptr = strrchr(tmp, '.');
  73. if (ptr == NULL) {
  74. ptr = tmp;
  75. } else {
  76. ptr = ptr + 1;
  77. }
  78. return dlsym(mod->module, ptr);
  79. }
  80. static int
  81. open_sym(struct skynet_module *mod) {
  82. mod->create = get_api(mod, "_create");
  83. mod->init = get_api(mod, "_init");
  84. mod->release = get_api(mod, "_release");
  85. mod->signal = get_api(mod, "_signal");
  86. return mod->init == NULL;
  87. }
  88. struct skynet_module *
  89. skynet_module_query(const char * name) {
  90. struct skynet_module * result = _query(name);
  91. if (result)
  92. return result;
  93. SPIN_LOCK(M)
  94. result = _query(name); // double check
  95. if (result == NULL && M->count < MAX_MODULE_TYPE) {
  96. int index = M->count;
  97. void * dl = _try_open(M,name);
  98. if (dl) {
  99. M->m[index].name = name;
  100. M->m[index].module = dl;
  101. if (open_sym(&M->m[index]) == 0) {
  102. M->m[index].name = skynet_strdup(name);
  103. M->count ++;
  104. result = &M->m[index];
  105. }
  106. }
  107. }
  108. SPIN_UNLOCK(M)
  109. return result;
  110. }
  111. void *
  112. skynet_module_instance_create(struct skynet_module *m) {
  113. if (m->create) {
  114. return m->create();
  115. } else {
  116. return (void *)(intptr_t)(~0);
  117. }
  118. }
  119. int
  120. skynet_module_instance_init(struct skynet_module *m, void * inst, struct skynet_context *ctx, const char * parm) {
  121. return m->init(inst, ctx, parm);
  122. }
  123. void
  124. skynet_module_instance_release(struct skynet_module *m, void *inst) {
  125. if (m->release) {
  126. m->release(inst);
  127. }
  128. }
  129. void
  130. skynet_module_instance_signal(struct skynet_module *m, void *inst, int signal) {
  131. if (m->signal) {
  132. m->signal(inst, signal);
  133. }
  134. }
  135. void
  136. skynet_module_init(const char *path) {
  137. struct modules *m = skynet_malloc(sizeof(*m));
  138. m->count = 0;
  139. m->path = skynet_strdup(path);
  140. SPIN_INIT(m)
  141. M = m;
  142. }