THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
8.0KB

  1. #include "cache.h"
  2. #include "config.h"
  3. #include "dir.h"
  4. #include "ewah/ewok.h"
  5. #include "fsmonitor.h"
  6. #include "run-command.h"
  7. #include "strbuf.h"
  8. #define INDEX_EXTENSION_VERSION (1)
  9. #define HOOK_INTERFACE_VERSION (1)
  10. struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR);
  11. static void fsmonitor_ewah_callback(size_t pos, void *is)
  12. {
  13. struct index_state *istate = (struct index_state *)is;
  14. struct cache_entry *ce;
  15. if (pos >= istate->cache_nr)
  16. BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" >= %u)",
  17. (uintmax_t)pos, istate->cache_nr);
  18. ce = istate->cache[pos];
  19. ce->ce_flags &= ~CE_FSMONITOR_VALID;
  20. }
  21. int read_fsmonitor_extension(struct index_state *istate, const void *data,
  22. unsigned long sz)
  23. {
  24. const char *index = data;
  25. uint32_t hdr_version;
  26. uint32_t ewah_size;
  27. struct ewah_bitmap *fsmonitor_dirty;
  28. int ret;
  29. if (sz < sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t))
  30. return error("corrupt fsmonitor extension (too short)");
  31. hdr_version = get_be32(index);
  32. index += sizeof(uint32_t);
  33. if (hdr_version != INDEX_EXTENSION_VERSION)
  34. return error("bad fsmonitor version %d", hdr_version);
  35. istate->fsmonitor_last_update = get_be64(index);
  36. index += sizeof(uint64_t);
  37. ewah_size = get_be32(index);
  38. index += sizeof(uint32_t);
  39. fsmonitor_dirty = ewah_new();
  40. ret = ewah_read_mmap(fsmonitor_dirty, index, ewah_size);
  41. if (ret != ewah_size) {
  42. ewah_free(fsmonitor_dirty);
  43. return error("failed to parse ewah bitmap reading fsmonitor index extension");
  44. }
  45. istate->fsmonitor_dirty = fsmonitor_dirty;
  46. if (istate->fsmonitor_dirty->bit_size > istate->cache_nr)
  47. BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
  48. (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
  49. trace_printf_key(&trace_fsmonitor, "read fsmonitor extension successful");
  50. return 0;
  51. }
  52. void fill_fsmonitor_bitmap(struct index_state *istate)
  53. {
  54. unsigned int i, skipped = 0;
  55. istate->fsmonitor_dirty = ewah_new();
  56. for (i = 0; i < istate->cache_nr; i++) {
  57. if (istate->cache[i]->ce_flags & CE_REMOVE)
  58. skipped++;
  59. else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
  60. ewah_set(istate->fsmonitor_dirty, i - skipped);
  61. }
  62. }
  63. void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate)
  64. {
  65. uint32_t hdr_version;
  66. uint64_t tm;
  67. uint32_t ewah_start;
  68. uint32_t ewah_size = 0;
  69. int fixup = 0;
  70. if (istate->fsmonitor_dirty->bit_size > istate->cache_nr)
  71. BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
  72. (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
  73. put_be32(&hdr_version, INDEX_EXTENSION_VERSION);
  74. strbuf_add(sb, &hdr_version, sizeof(uint32_t));
  75. put_be64(&tm, istate->fsmonitor_last_update);
  76. strbuf_add(sb, &tm, sizeof(uint64_t));
  77. fixup = sb->len;
  78. strbuf_add(sb, &ewah_size, sizeof(uint32_t)); /* we'll fix this up later */
  79. ewah_start = sb->len;
  80. ewah_serialize_strbuf(istate->fsmonitor_dirty, sb);
  81. ewah_free(istate->fsmonitor_dirty);
  82. istate->fsmonitor_dirty = NULL;
  83. /* fix up size field */
  84. put_be32(&ewah_size, sb->len - ewah_start);
  85. memcpy(sb->buf + fixup, &ewah_size, sizeof(uint32_t));
  86. trace_printf_key(&trace_fsmonitor, "write fsmonitor extension successful");
  87. }
  88. /*
  89. * Call the query-fsmonitor hook passing the time of the last saved results.
  90. */
  91. static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *query_result)
  92. {
  93. struct child_process cp = CHILD_PROCESS_INIT;
  94. if (!core_fsmonitor)
  95. return -1;
  96. argv_array_push(&cp.args, core_fsmonitor);
  97. argv_array_pushf(&cp.args, "%d", version);
  98. argv_array_pushf(&cp.args, "%" PRIuMAX, (uintmax_t)last_update);
  99. cp.use_shell = 1;
  100. cp.dir = get_git_work_tree();
  101. return capture_command(&cp, query_result, 1024);
  102. }
  103. static void fsmonitor_refresh_callback(struct index_state *istate, const char *name)
  104. {
  105. int pos = index_name_pos(istate, name, strlen(name));
  106. if (pos >= 0) {
  107. struct cache_entry *ce = istate->cache[pos];
  108. ce->ce_flags &= ~CE_FSMONITOR_VALID;
  109. }
  110. /*
  111. * Mark the untracked cache dirty even if it wasn't found in the index
  112. * as it could be a new untracked file.
  113. */
  114. trace_printf_key(&trace_fsmonitor, "fsmonitor_refresh_callback '%s'", name);
  115. untracked_cache_invalidate_path(istate, name, 0);
  116. }
  117. void refresh_fsmonitor(struct index_state *istate)
  118. {
  119. struct strbuf query_result = STRBUF_INIT;
  120. int query_success = 0;
  121. size_t bol; /* beginning of line */
  122. uint64_t last_update;
  123. char *buf;
  124. unsigned int i;
  125. if (!core_fsmonitor || istate->fsmonitor_has_run_once)
  126. return;
  127. istate->fsmonitor_has_run_once = 1;
  128. trace_printf_key(&trace_fsmonitor, "refresh fsmonitor");
  129. /*
  130. * This could be racy so save the date/time now and query_fsmonitor
  131. * should be inclusive to ensure we don't miss potential changes.
  132. */
  133. last_update = getnanotime();
  134. /*
  135. * If we have a last update time, call query_fsmonitor for the set of
  136. * changes since that time, else assume everything is possibly dirty
  137. * and check it all.
  138. */
  139. if (istate->fsmonitor_last_update) {
  140. query_success = !query_fsmonitor(HOOK_INTERFACE_VERSION,
  141. istate->fsmonitor_last_update, &query_result);
  142. trace_performance_since(last_update, "fsmonitor process '%s'", core_fsmonitor);
  143. trace_printf_key(&trace_fsmonitor, "fsmonitor process '%s' returned %s",
  144. core_fsmonitor, query_success ? "success" : "failure");
  145. }
  146. /* a fsmonitor process can return '/' to indicate all entries are invalid */
  147. if (query_success && query_result.buf[0] != '/') {
  148. /* Mark all entries returned by the monitor as dirty */
  149. buf = query_result.buf;
  150. bol = 0;
  151. for (i = 0; i < query_result.len; i++) {
  152. if (buf[i] != '\0')
  153. continue;
  154. fsmonitor_refresh_callback(istate, buf + bol);
  155. bol = i + 1;
  156. }
  157. if (bol < query_result.len)
  158. fsmonitor_refresh_callback(istate, buf + bol);
  159. } else {
  160. /* Mark all entries invalid */
  161. for (i = 0; i < istate->cache_nr; i++)
  162. istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
  163. /* If we're going to check every file, ensure we save the results */
  164. istate->cache_changed |= FSMONITOR_CHANGED;
  165. if (istate->untracked)
  166. istate->untracked->use_fsmonitor = 0;
  167. }
  168. strbuf_release(&query_result);
  169. /* Now that we've updated istate, save the last_update time */
  170. istate->fsmonitor_last_update = last_update;
  171. }
  172. void add_fsmonitor(struct index_state *istate)
  173. {
  174. unsigned int i;
  175. if (!istate->fsmonitor_last_update) {
  176. trace_printf_key(&trace_fsmonitor, "add fsmonitor");
  177. istate->cache_changed |= FSMONITOR_CHANGED;
  178. istate->fsmonitor_last_update = getnanotime();
  179. /* reset the fsmonitor state */
  180. for (i = 0; i < istate->cache_nr; i++)
  181. istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
  182. /* reset the untracked cache */
  183. if (istate->untracked) {
  184. add_untracked_cache(istate);
  185. istate->untracked->use_fsmonitor = 1;
  186. }
  187. /* Update the fsmonitor state */
  188. refresh_fsmonitor(istate);
  189. }
  190. }
  191. void remove_fsmonitor(struct index_state *istate)
  192. {
  193. if (istate->fsmonitor_last_update) {
  194. trace_printf_key(&trace_fsmonitor, "remove fsmonitor");
  195. istate->cache_changed |= FSMONITOR_CHANGED;
  196. istate->fsmonitor_last_update = 0;
  197. }
  198. }
  199. void tweak_fsmonitor(struct index_state *istate)
  200. {
  201. unsigned int i;
  202. int fsmonitor_enabled = git_config_get_fsmonitor();
  203. if (istate->fsmonitor_dirty) {
  204. if (fsmonitor_enabled) {
  205. /* Mark all entries valid */
  206. for (i = 0; i < istate->cache_nr; i++) {
  207. istate->cache[i]->ce_flags |= CE_FSMONITOR_VALID;
  208. }
  209. /* Mark all previously saved entries as dirty */
  210. if (istate->fsmonitor_dirty->bit_size > istate->cache_nr)
  211. BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)",
  212. (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr);
  213. ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate);
  214. /* Now mark the untracked cache for fsmonitor usage */
  215. if (istate->untracked)
  216. istate->untracked->use_fsmonitor = 1;
  217. }
  218. ewah_free(istate->fsmonitor_dirty);
  219. istate->fsmonitor_dirty = NULL;
  220. }
  221. switch (fsmonitor_enabled) {
  222. case -1: /* keep: do nothing */
  223. break;
  224. case 0: /* false */
  225. remove_fsmonitor(istate);
  226. break;
  227. case 1: /* true */
  228. add_fsmonitor(istate);
  229. break;
  230. default: /* unknown value: do nothing */
  231. break;
  232. }
  233. }