Merge of r4498:
Fix of rbtree lookup on hash collisions.
Previous code incorrectly assumed that nodes with identical keys are linked
together. This might not be true after tree rebalance.
Patch by Lanshun Zhou.
Maxim Dounin
8 years ago
836 | 836 | |
837 | 837 | /* hash == node->key */ |
838 | 838 | |
839 | do { | |
840 | file = (ngx_cached_open_file_t *) node; | |
841 | ||
842 | rc = ngx_strcmp(name->data, file->name); | |
843 | ||
844 | if (rc == 0) { | |
845 | return file; | |
846 | } | |
847 | ||
848 | node = (rc < 0) ? node->left : node->right; | |
849 | ||
850 | } while (node != sentinel && hash == node->key); | |
851 | ||
852 | break; | |
839 | file = (ngx_cached_open_file_t *) node; | |
840 | ||
841 | rc = ngx_strcmp(name->data, file->name); | |
842 | ||
843 | if (rc == 0) { | |
844 | return file; | |
845 | } | |
846 | ||
847 | node = (rc < 0) ? node->left : node->right; | |
853 | 848 | } |
854 | 849 | |
855 | 850 | return NULL; |
1625 | 1625 | |
1626 | 1626 | /* hash == node->key */ |
1627 | 1627 | |
1628 | do { | |
1629 | rn = (ngx_resolver_node_t *) node; | |
1630 | ||
1631 | rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen); | |
1632 | ||
1633 | if (rc == 0) { | |
1634 | return rn; | |
1635 | } | |
1636 | ||
1637 | node = (rc < 0) ? node->left : node->right; | |
1638 | ||
1639 | } while (node != sentinel && hash == node->key); | |
1640 | ||
1641 | break; | |
1628 | rn = (ngx_resolver_node_t *) node; | |
1629 | ||
1630 | rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen); | |
1631 | ||
1632 | if (rc == 0) { | |
1633 | return rn; | |
1634 | } | |
1635 | ||
1636 | node = (rc < 0) ? node->left : node->right; | |
1642 | 1637 | } |
1643 | 1638 | |
1644 | 1639 | /* not found */ |
1800 | 1800 | |
1801 | 1801 | /* hash == node->key */ |
1802 | 1802 | |
1803 | do { | |
1804 | sess_id = (ngx_ssl_sess_id_t *) node; | |
1805 | ||
1806 | rc = ngx_memn2cmp(id, sess_id->id, | |
1807 | (size_t) len, (size_t) node->data); | |
1808 | if (rc == 0) { | |
1809 | ||
1810 | if (sess_id->expire > ngx_time()) { | |
1811 | ngx_memcpy(buf, sess_id->session, sess_id->len); | |
1812 | ||
1813 | ngx_shmtx_unlock(&shpool->mutex); | |
1814 | ||
1815 | p = buf; | |
1816 | sess = d2i_SSL_SESSION(NULL, &p, sess_id->len); | |
1817 | ||
1818 | return sess; | |
1819 | } | |
1820 | ||
1821 | ngx_queue_remove(&sess_id->queue); | |
1822 | ||
1823 | ngx_rbtree_delete(&cache->session_rbtree, node); | |
1824 | ||
1825 | ngx_slab_free_locked(shpool, sess_id->session); | |
1803 | sess_id = (ngx_ssl_sess_id_t *) node; | |
1804 | ||
1805 | rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data); | |
1806 | ||
1807 | if (rc == 0) { | |
1808 | ||
1809 | if (sess_id->expire > ngx_time()) { | |
1810 | ngx_memcpy(buf, sess_id->session, sess_id->len); | |
1811 | ||
1812 | ngx_shmtx_unlock(&shpool->mutex); | |
1813 | ||
1814 | p = buf; | |
1815 | sess = d2i_SSL_SESSION(NULL, &p, sess_id->len); | |
1816 | ||
1817 | return sess; | |
1818 | } | |
1819 | ||
1820 | ngx_queue_remove(&sess_id->queue); | |
1821 | ||
1822 | ngx_rbtree_delete(&cache->session_rbtree, node); | |
1823 | ||
1824 | ngx_slab_free_locked(shpool, sess_id->session); | |
1826 | 1825 | #if (NGX_PTR_SIZE == 4) |
1827 | ngx_slab_free_locked(shpool, sess_id->id); | |
1826 | ngx_slab_free_locked(shpool, sess_id->id); | |
1828 | 1827 | #endif |
1829 | ngx_slab_free_locked(shpool, sess_id); | |
1830 | ||
1831 | sess = NULL; | |
1832 | ||
1833 | goto done; | |
1834 | } | |
1835 | ||
1836 | node = (rc < 0) ? node->left : node->right; | |
1837 | ||
1838 | } while (node != sentinel && hash == node->key); | |
1839 | ||
1840 | break; | |
1828 | ngx_slab_free_locked(shpool, sess_id); | |
1829 | ||
1830 | sess = NULL; | |
1831 | ||
1832 | goto done; | |
1833 | } | |
1834 | ||
1835 | node = (rc < 0) ? node->left : node->right; | |
1841 | 1836 | } |
1842 | 1837 | |
1843 | 1838 | done: |
1907 | 1902 | |
1908 | 1903 | /* hash == node->key */ |
1909 | 1904 | |
1910 | do { | |
1911 | sess_id = (ngx_ssl_sess_id_t *) node; | |
1912 | ||
1913 | rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data); | |
1914 | ||
1915 | if (rc == 0) { | |
1916 | ||
1917 | ngx_queue_remove(&sess_id->queue); | |
1918 | ||
1919 | ngx_rbtree_delete(&cache->session_rbtree, node); | |
1920 | ||
1921 | ngx_slab_free_locked(shpool, sess_id->session); | |
1905 | sess_id = (ngx_ssl_sess_id_t *) node; | |
1906 | ||
1907 | rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data); | |
1908 | ||
1909 | if (rc == 0) { | |
1910 | ||
1911 | ngx_queue_remove(&sess_id->queue); | |
1912 | ||
1913 | ngx_rbtree_delete(&cache->session_rbtree, node); | |
1914 | ||
1915 | ngx_slab_free_locked(shpool, sess_id->session); | |
1922 | 1916 | #if (NGX_PTR_SIZE == 4) |
1923 | ngx_slab_free_locked(shpool, sess_id->id); | |
1917 | ngx_slab_free_locked(shpool, sess_id->id); | |
1924 | 1918 | #endif |
1925 | ngx_slab_free_locked(shpool, sess_id); | |
1926 | ||
1927 | goto done; | |
1928 | } | |
1929 | ||
1930 | node = (rc < 0) ? node->left : node->right; | |
1931 | ||
1932 | } while (node != sentinel && hash == node->key); | |
1933 | ||
1934 | break; | |
1919 | ngx_slab_free_locked(shpool, sess_id); | |
1920 | ||
1921 | goto done; | |
1922 | } | |
1923 | ||
1924 | node = (rc < 0) ? node->left : node->right; | |
1935 | 1925 | } |
1936 | 1926 | |
1937 | 1927 | done: |
371 | 371 | |
372 | 372 | /* hash == node->key */ |
373 | 373 | |
374 | do { | |
375 | lr = (ngx_http_limit_req_node_t *) &node->color; | |
376 | ||
377 | rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); | |
378 | ||
379 | if (rc == 0) { | |
380 | ngx_queue_remove(&lr->queue); | |
381 | ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); | |
382 | ||
383 | tp = ngx_timeofday(); | |
384 | ||
385 | now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
386 | ms = (ngx_msec_int_t) (now - lr->last); | |
387 | ||
388 | excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; | |
389 | ||
390 | if (excess < 0) { | |
391 | excess = 0; | |
392 | } | |
393 | ||
394 | *ep = excess; | |
395 | ||
396 | if ((ngx_uint_t) excess > lrcf->burst) { | |
397 | return NGX_BUSY; | |
398 | } | |
399 | ||
400 | lr->excess = excess; | |
401 | lr->last = now; | |
402 | ||
403 | if (excess) { | |
404 | return NGX_AGAIN; | |
405 | } | |
406 | ||
407 | return NGX_OK; | |
408 | } | |
409 | ||
410 | node = (rc < 0) ? node->left : node->right; | |
411 | ||
412 | } while (node != sentinel && hash == node->key); | |
413 | ||
414 | break; | |
374 | lr = (ngx_http_limit_req_node_t *) &node->color; | |
375 | ||
376 | rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); | |
377 | ||
378 | if (rc == 0) { | |
379 | ngx_queue_remove(&lr->queue); | |
380 | ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); | |
381 | ||
382 | tp = ngx_timeofday(); | |
383 | ||
384 | now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
385 | ms = (ngx_msec_int_t) (now - lr->last); | |
386 | ||
387 | excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; | |
388 | ||
389 | if (excess < 0) { | |
390 | excess = 0; | |
391 | } | |
392 | ||
393 | *ep = excess; | |
394 | ||
395 | if ((ngx_uint_t) excess > lrcf->burst) { | |
396 | return NGX_BUSY; | |
397 | } | |
398 | ||
399 | lr->excess = excess; | |
400 | lr->last = now; | |
401 | ||
402 | if (excess) { | |
403 | return NGX_AGAIN; | |
404 | } | |
405 | ||
406 | return NGX_OK; | |
407 | } | |
408 | ||
409 | node = (rc < 0) ? node->left : node->right; | |
415 | 410 | } |
416 | 411 | |
417 | 412 | *ep = 0; |
193 | 193 | |
194 | 194 | /* hash == node->key */ |
195 | 195 | |
196 | do { | |
197 | lz = (ngx_http_limit_zone_node_t *) &node->color; | |
198 | ||
199 | rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len); | |
200 | ||
201 | if (rc == 0) { | |
202 | if ((ngx_uint_t) lz->conn < lzcf->conn) { | |
203 | lz->conn++; | |
204 | goto done; | |
205 | } | |
206 | ||
207 | ngx_shmtx_unlock(&shpool->mutex); | |
208 | ||
209 | ngx_log_error(lzcf->log_level, r->connection->log, 0, | |
210 | "limiting connections by zone \"%V\"", | |
211 | &lzcf->shm_zone->shm.name); | |
212 | ||
213 | return NGX_HTTP_SERVICE_UNAVAILABLE; | |
196 | lz = (ngx_http_limit_zone_node_t *) &node->color; | |
197 | ||
198 | rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len); | |
199 | ||
200 | if (rc == 0) { | |
201 | if ((ngx_uint_t) lz->conn < lzcf->conn) { | |
202 | lz->conn++; | |
203 | goto done; | |
214 | 204 | } |
215 | 205 | |
216 | node = (rc < 0) ? node->left : node->right; | |
217 | ||
218 | } while (node != sentinel && hash == node->key); | |
219 | ||
220 | break; | |
206 | ngx_shmtx_unlock(&shpool->mutex); | |
207 | ||
208 | ngx_log_error(lzcf->log_level, r->connection->log, 0, | |
209 | "limiting connections by zone \"%V\"", | |
210 | &lzcf->shm_zone->shm.name); | |
211 | ||
212 | return NGX_HTTP_SERVICE_UNAVAILABLE; | |
213 | } | |
214 | ||
215 | node = (rc < 0) ? node->left : node->right; | |
221 | 216 | } |
222 | 217 | |
223 | 218 | n = offsetof(ngx_rbtree_node_t, color) |
672 | 672 | |
673 | 673 | /* node_key == node->key */ |
674 | 674 | |
675 | do { | |
676 | fcn = (ngx_http_file_cache_node_t *) node; | |
677 | ||
678 | rc = ngx_memcmp(&key[sizeof(ngx_rbtree_key_t)], fcn->key, | |
679 | NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); | |
680 | ||
681 | if (rc == 0) { | |
682 | return fcn; | |
683 | } | |
684 | ||
685 | node = (rc < 0) ? node->left : node->right; | |
686 | ||
687 | } while (node != sentinel && node_key == node->key); | |
688 | ||
689 | break; | |
675 | fcn = (ngx_http_file_cache_node_t *) node; | |
676 | ||
677 | rc = ngx_memcmp(&key[sizeof(ngx_rbtree_key_t)], fcn->key, | |
678 | NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); | |
679 | ||
680 | if (rc == 0) { | |
681 | return fcn; | |
682 | } | |
683 | ||
684 | node = (rc < 0) ? node->left : node->right; | |
690 | 685 | } |
691 | 686 | |
692 | 687 | /* not found */ |