@@ -221,6 +221,9 @@ static char ngx_http_lua_ssl_session_metatable_key;
221
221
#endif
222
222
223
223
224
+ #define ngx_http_lua_tcp_socket_metatable_literal_key "__tcp_cosocket_mt"
225
+
226
+
224
227
void
225
228
ngx_http_lua_inject_socket_tcp_api (ngx_log_t * log , lua_State * L )
226
229
{
@@ -355,6 +358,12 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
355
358
lua_pushvalue (L , -1 );
356
359
lua_setfield (L , -2 , "__index" );
357
360
lua_rawset (L , LUA_REGISTRYINDEX );
361
+
362
+ lua_pushliteral (L , ngx_http_lua_tcp_socket_metatable_literal_key );
363
+ lua_pushlightuserdata (L , ngx_http_lua_lightudata_mask (
364
+ tcp_socket_metatable_key ));
365
+ lua_rawget (L , LUA_REGISTRYINDEX );
366
+ lua_rawset (L , LUA_REGISTRYINDEX );
358
367
/* }}} */
359
368
360
369
/* {{{upstream userdata metatable */
@@ -5382,6 +5391,8 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L)
5382
5391
item -> socklen = pc -> socklen ;
5383
5392
ngx_memcpy (& item -> sockaddr , pc -> sockaddr , pc -> socklen );
5384
5393
item -> reused = u -> reused ;
5394
+ item -> udata_queue = u -> udata_queue ;
5395
+ u -> udata_queue = NULL ;
5385
5396
5386
5397
if (c -> read -> ready ) {
5387
5398
rc = ngx_http_lua_socket_keepalive_close_handler (c -> read );
@@ -5457,6 +5468,8 @@ ngx_http_lua_get_keepalive_peer(ngx_http_request_t *r,
5457
5468
pc -> cached = 1 ;
5458
5469
5459
5470
u -> reused = item -> reused + 1 ;
5471
+ u -> udata_queue = item -> udata_queue ;
5472
+ item -> udata_queue = NULL ;
5460
5473
5461
5474
#if 1
5462
5475
u -> write_event_handler = ngx_http_lua_socket_dummy_handler ;
@@ -6151,4 +6164,235 @@ ngx_http_lua_cleanup_conn_pools(lua_State *L)
6151
6164
lua_pop (L , 1 );
6152
6165
}
6153
6166
6167
+
6168
+ int
6169
+ ngx_http_lua_ffi_socket_tcp_init_udata_queue (
6170
+ ngx_http_lua_socket_tcp_upstream_t * u , int capacity , char * * err_msg )
6171
+ {
6172
+ int i , max_size ;
6173
+ ngx_pool_t * pool ;
6174
+ ngx_http_lua_socket_udata_queue_t * udata_queue ;
6175
+ ngx_http_lua_socket_node_t * node ;
6176
+
6177
+ pool = u -> peer .connection -> pool ;
6178
+
6179
+ if (u -> udata_queue == NULL ) {
6180
+ max_size = capacity ;
6181
+ if (max_size == 0 ) {
6182
+ max_size = 4 ;
6183
+ }
6184
+
6185
+ udata_queue = ngx_palloc (pool ,
6186
+ sizeof (ngx_http_lua_socket_udata_queue_t ) +
6187
+ sizeof (ngx_http_lua_socket_node_t ) * max_size );
6188
+
6189
+ if (udata_queue == NULL ) {
6190
+ * err_msg = "no memory" ;
6191
+ return NGX_ERROR ;
6192
+ }
6193
+
6194
+ udata_queue -> pool = pool ;
6195
+ udata_queue -> capacity = capacity ;
6196
+ udata_queue -> len = 0 ;
6197
+ ngx_queue_init (& udata_queue -> queue );
6198
+ ngx_queue_init (& udata_queue -> free );
6199
+
6200
+ node = (ngx_http_lua_socket_node_t * ) (udata_queue + 1 );
6201
+
6202
+ for (i = 0 ; i < max_size ; i ++ ) {
6203
+ ngx_queue_insert_head (& udata_queue -> free , & node -> queue );
6204
+ node ++ ;
6205
+ }
6206
+
6207
+ u -> udata_queue = udata_queue ;
6208
+
6209
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log , 0 ,
6210
+ "init udata_queue %uD, cosocket %p udata %p" ,
6211
+ capacity , u , udata_queue );
6212
+ }
6213
+
6214
+ return NGX_OK ;
6215
+ }
6216
+
6217
+
6218
+ int
6219
+ ngx_http_lua_ffi_socket_tcp_count_udata (ngx_http_lua_socket_tcp_upstream_t * u )
6220
+ {
6221
+ /* return NGX_ERROR (-1) for missing udata_queue to
6222
+ * distinguish it from empty udata_queue */
6223
+ if (u -> udata_queue == NULL ) {
6224
+ return NGX_ERROR ;
6225
+ }
6226
+
6227
+ return u -> udata_queue -> len ;
6228
+ }
6229
+
6230
+
6231
+ int
6232
+ ngx_http_lua_ffi_socket_tcp_add_udata (ngx_http_lua_socket_tcp_upstream_t * u ,
6233
+ uint64_t key , uint64_t value , uint64_t * evicted_key ,
6234
+ uint64_t * evicted_value , char * * err_msg )
6235
+ {
6236
+ int evicted = 0 ;
6237
+ ngx_pool_t * pool ;
6238
+ ngx_http_lua_socket_node_t * node = NULL ;
6239
+ ngx_queue_t * q , * uqueue ;
6240
+
6241
+ pool = u -> peer .connection -> pool ;
6242
+
6243
+ if (u -> udata_queue == NULL ) {
6244
+ * err_msg = "no udata queue" ;
6245
+ return NGX_ERROR ;
6246
+ }
6247
+
6248
+ uqueue = & u -> udata_queue -> queue ;
6249
+
6250
+ for (q = ngx_queue_head (uqueue );
6251
+ q != ngx_queue_sentinel (uqueue );
6252
+ q = ngx_queue_next (q ))
6253
+ {
6254
+ node = ngx_queue_data (q , ngx_http_lua_socket_node_t , queue );
6255
+
6256
+ if (node -> key == key ) {
6257
+ /* key exists */
6258
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log , 0 ,
6259
+ "found %uD, cosocket %p udata %p" ,
6260
+ key , u , u -> udata_queue );
6261
+ ngx_queue_remove (q );
6262
+ node -> value = value ;
6263
+
6264
+ break ;
6265
+ }
6266
+ }
6267
+
6268
+ if (q == ngx_queue_sentinel (uqueue )) {
6269
+
6270
+ if (u -> udata_queue -> capacity
6271
+ && u -> udata_queue -> capacity == u -> udata_queue -> len )
6272
+ {
6273
+ /* evict key */
6274
+ q = ngx_queue_last (uqueue );
6275
+ node = ngx_queue_data (q , ngx_http_lua_socket_node_t , queue );
6276
+ ngx_queue_remove (q );
6277
+ ngx_log_debug4 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log , 0 ,
6278
+ "evict %uD for %uD, cosocket %p udata %p" ,
6279
+ node -> key , key , u , u -> udata_queue );
6280
+ * evicted_key = node -> key ;
6281
+ * evicted_value = node -> value ;
6282
+ evicted = 1 ;
6283
+
6284
+ } else {
6285
+ /* insert key */
6286
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log , 0 ,
6287
+ "insert %uD, cosocket %p udata %p" ,
6288
+ key , u , u -> udata_queue );
6289
+
6290
+ if (!ngx_queue_empty (& u -> udata_queue -> free )) {
6291
+ q = ngx_queue_head (& u -> udata_queue -> free );
6292
+ node = ngx_queue_data (q , ngx_http_lua_socket_node_t , queue );
6293
+ ngx_queue_remove (q );
6294
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log ,
6295
+ 0 , "reuse free node %p, cosocket %p udata %p" ,
6296
+ node , u , u -> udata_queue );
6297
+
6298
+ } else {
6299
+ node = ngx_palloc (pool , sizeof (ngx_http_lua_socket_node_t ));
6300
+ if (node == NULL ) {
6301
+ goto nomem ;
6302
+ }
6303
+
6304
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log ,
6305
+ 0 , "allocate new node %p, cosocket %p udata %p" ,
6306
+ node , u , u -> udata_queue );
6307
+ }
6308
+
6309
+ u -> udata_queue -> len ++ ;
6310
+ }
6311
+
6312
+ node -> key = key ;
6313
+ node -> value = value ;
6314
+ }
6315
+
6316
+ ngx_queue_insert_head (uqueue , & node -> queue );
6317
+ return evicted ? NGX_DONE : NGX_OK ;
6318
+
6319
+ nomem :
6320
+
6321
+ * err_msg = "no memory" ;
6322
+ return NGX_ERROR ;
6323
+ }
6324
+
6325
+
6326
+ int
6327
+ ngx_http_lua_ffi_socket_tcp_get_udata (ngx_http_lua_socket_tcp_upstream_t * u ,
6328
+ uint64_t key , uint64_t * value , char * * err_msg )
6329
+ {
6330
+ ngx_http_lua_socket_node_t * node ;
6331
+ ngx_queue_t * q , * uqueue ;
6332
+
6333
+ if (u -> udata_queue == NULL ) {
6334
+ * err_msg = "no udata queue" ;
6335
+ return NGX_ERROR ;
6336
+ }
6337
+
6338
+ uqueue = & u -> udata_queue -> queue ;
6339
+
6340
+ for (q = ngx_queue_head (uqueue );
6341
+ q != ngx_queue_sentinel (uqueue );
6342
+ q = ngx_queue_next (q ))
6343
+ {
6344
+ node = ngx_queue_data (q , ngx_http_lua_socket_node_t , queue );
6345
+
6346
+ if (node -> key == key ) {
6347
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log , 0 ,
6348
+ "found %uD, cosocket %p udata %p" ,
6349
+ key , u , u -> udata_queue );
6350
+ ngx_queue_remove (q );
6351
+ ngx_queue_insert_head (uqueue , & node -> queue );
6352
+ * value = node -> value ;
6353
+ return NGX_OK ;
6354
+ }
6355
+ }
6356
+
6357
+ * err_msg = "not found" ;
6358
+ return NGX_ERROR ;
6359
+ }
6360
+
6361
+
6362
+ int
6363
+ ngx_http_lua_ffi_socket_tcp_del_udata (ngx_http_lua_socket_tcp_upstream_t * u ,
6364
+ uint64_t key , char * * err_msg )
6365
+ {
6366
+ ngx_http_lua_socket_node_t * node ;
6367
+ ngx_queue_t * q , * uqueue ;
6368
+
6369
+ if (u -> udata_queue == NULL ) {
6370
+ * err_msg = "no udata queue" ;
6371
+ return NGX_ERROR ;
6372
+ }
6373
+
6374
+ uqueue = & u -> udata_queue -> queue ;
6375
+
6376
+ for (q = ngx_queue_head (uqueue );
6377
+ q != ngx_queue_sentinel (uqueue );
6378
+ q = ngx_queue_next (q ))
6379
+ {
6380
+ node = ngx_queue_data (q , ngx_http_lua_socket_node_t , queue );
6381
+
6382
+ if (node -> key == key ) {
6383
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP , u -> request -> connection -> log , 0 ,
6384
+ "delete %uD, cosocket %p udata %p" ,
6385
+ key , u , u -> udata_queue );
6386
+ ngx_queue_remove (q );
6387
+ ngx_queue_insert_head (& u -> udata_queue -> free , & node -> queue );
6388
+ u -> udata_queue -> len -- ;
6389
+ return NGX_OK ;
6390
+ }
6391
+ }
6392
+
6393
+ * err_msg = "not found" ;
6394
+ return NGX_ERROR ;
6395
+ }
6396
+
6397
+
6154
6398
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
0 commit comments