| 145 | } |
| 146 | |
| 147 | void SlowLog_Add |
| 148 | ( |
| 149 | SlowLog *slowlog, |
| 150 | const char *cmd, |
| 151 | const char *query, |
| 152 | double latency, |
| 153 | time_t *t |
| 154 | ) { |
| 155 | ASSERT(latency >= 0); |
| 156 | ASSERT(cmd != NULL); |
| 157 | ASSERT(query != NULL); |
| 158 | ASSERT(slowlog != NULL); |
| 159 | |
| 160 | int res; |
| 161 | UNUSED(res); |
| 162 | char *key; |
| 163 | time_t _time; |
| 164 | SlowLogItem *existing_item; |
| 165 | int t_id = ThreadPools_GetThreadID(); |
| 166 | rax *lookup = slowlog->lookup[t_id]; |
| 167 | heap_t *heap = slowlog->min_heap[t_id]; |
| 168 | pthread_mutex_t *lock = slowlog->locks + t_id; |
| 169 | |
| 170 | // initialise time |
| 171 | (t) ? _time = *t : time(&_time); |
| 172 | |
| 173 | if(pthread_mutex_lock(lock) != 0) { |
| 174 | // failed to lock, skip logging |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | { |
| 179 | // in critical section |
| 180 | bool exists = _SlowLog_Contains(slowlog, t_id, cmd, query, &key, |
| 181 | &existing_item); |
| 182 | size_t key_len = strlen(key); |
| 183 | |
| 184 | if(exists) { |
| 185 | // a similar item already exists |
| 186 | // see if we need to update its latency |
| 187 | if(existing_item->latency < latency) { |
| 188 | existing_item->time = _time; |
| 189 | existing_item->latency = latency; |
| 190 | } |
| 191 | goto cleanup; |
| 192 | } |
| 193 | |
| 194 | // similar item does not exist in the log |
| 195 | // check if there's enough room to store item |
| 196 | int introduce_item = 0; |
| 197 | if(Heap_count(heap) < SLOW_LOG_SIZE) { |
| 198 | introduce_item = 1; |
| 199 | } else { |
| 200 | // not enough room, see if item should be tracked |
| 201 | SlowLogItem *top = Heap_peek(heap); |
| 202 | if(top->latency < latency) { |
| 203 | top = Heap_poll(heap); |
| 204 | _SlowLog_RemoveItemFromLookup(slowlog, t_id, top); |
no test coverage detected