Perform incremental defragmentation work from the serverCron. * This works in a similar way to activeExpireCycle, in the sense that * we do incremental work across calls. */
| 1096 | * This works in a similar way to activeExpireCycle, in the sense that |
| 1097 | * we do incremental work across calls. */ |
| 1098 | void activeDefragCycle(void) { |
| 1099 | static int current_db = -1; |
| 1100 | static unsigned long cursor = 0; |
| 1101 | static redisDb *db = NULL; |
| 1102 | static long long start_scan, start_stat; |
| 1103 | unsigned int iterations = 0; |
| 1104 | unsigned long long prev_defragged = g_pserver->stat_active_defrag_hits; |
| 1105 | unsigned long long prev_scanned = g_pserver->stat_active_defrag_scanned; |
| 1106 | long long start, timelimit, endtime; |
| 1107 | mstime_t latency; |
| 1108 | int quit = 0; |
| 1109 | |
| 1110 | if (!cserver.active_defrag_enabled) { |
| 1111 | if (g_pserver->active_defrag_running) { |
| 1112 | /* if active defrag was disabled mid-run, start from fresh next time. */ |
| 1113 | g_pserver->active_defrag_running = 0; |
| 1114 | if (db) |
| 1115 | listEmpty(db->defrag_later); |
| 1116 | defrag_later_current_key = NULL; |
| 1117 | defrag_later_cursor = 0; |
| 1118 | current_db = -1; |
| 1119 | cursor = 0; |
| 1120 | db = NULL; |
| 1121 | } |
| 1122 | return; |
| 1123 | } |
| 1124 | |
| 1125 | if (hasActiveChildProcess()) |
| 1126 | return; /* Defragging memory while there's a fork will just do damage. */ |
| 1127 | |
| 1128 | /* Once a second, check if the fragmentation justfies starting a scan |
| 1129 | * or making it more aggressive. */ |
| 1130 | run_with_period(1000) { |
| 1131 | computeDefragCycles(); |
| 1132 | } |
| 1133 | if (!g_pserver->active_defrag_running) |
| 1134 | return; |
| 1135 | |
| 1136 | /* See activeExpireCycle for how timelimit is handled. */ |
| 1137 | start = ustime(); |
| 1138 | timelimit = 1000000*g_pserver->active_defrag_running/g_pserver->hz/100; |
| 1139 | if (timelimit <= 0) timelimit = 1; |
| 1140 | endtime = start + timelimit; |
| 1141 | latencyStartMonitor(latency); |
| 1142 | |
| 1143 | do { |
| 1144 | /* if we're not continuing a scan from the last call or loop, start a new one */ |
| 1145 | if (!cursor) { |
| 1146 | /* finish any leftovers from previous db before moving to the next one */ |
| 1147 | if (db && defragLaterStep(db, endtime)) { |
| 1148 | quit = 1; /* time is up, we didn't finish all the work */ |
| 1149 | break; /* this will exit the function and we'll continue on the next cycle */ |
| 1150 | } |
| 1151 | |
| 1152 | /* Move on to next database, and stop if we reached the last one. */ |
| 1153 | if (++current_db >= cserver.dbnum) { |
| 1154 | /* defrag other items not part of the db / keys */ |
| 1155 | defragOtherGlobals(); |
no test coverage detected