147
147
-export ([start_link /0 , start_link /2 , init /1 , handle_call /3 , handle_cast /2 ,
148
148
handle_info /2 , terminate /2 , code_change /3 , prioritise_cast /3 ]).
149
149
150
+ -export ([clear_metrics_of /1 , list_elders /0 , list_clients /0 , get_client_state /1 ]).
151
+
150
152
-define (SERVER , ? MODULE ).
151
153
% % Reserve 3 handles for ra usage: wal, segment writer and a dets table
152
154
-define (RESERVED_FOR_OTHERS , 100 + 3 ).
158
160
-define (CLIENT_ETS_TABLE , file_handle_cache_client ).
159
161
-define (ELDERS_ETS_TABLE , file_handle_cache_elders ).
160
162
163
+ -import (rabbit_misc , [safe_ets_update_counter /3 , safe_ets_update_counter /4 ,
164
+ safe_ets_update_element /3 , safe_ets_update_element /4 ]).
165
+
161
166
% %----------------------------------------------------------------------------
162
167
163
168
-record (file ,
@@ -622,6 +627,34 @@ clear_process_read_cache() ->
622
627
size (Handle # handle .read_buffer ) > 0
623
628
].
624
629
630
+ % % Only used for testing
631
+ clear_metrics_of (Pid ) ->
632
+ case whereis (? SERVER ) of
633
+ undefined -> ok ;
634
+ _ -> gen_server2 :cast (? SERVER , {clear_metrics_of , Pid })
635
+ end .
636
+
637
+ % % Only used for testing
638
+ list_elders () ->
639
+ case whereis (? SERVER ) of
640
+ undefined -> ok ;
641
+ _ -> gen_server2 :call (? SERVER , list_elders )
642
+ end .
643
+
644
+ % % Only used for testing
645
+ list_clients () ->
646
+ case whereis (? SERVER ) of
647
+ undefined -> ok ;
648
+ _ -> gen_server2 :call (? SERVER , list_clients )
649
+ end .
650
+
651
+ % % Only used for testing
652
+ get_client_state (Pid ) ->
653
+ case whereis (? SERVER ) of
654
+ undefined -> ok ;
655
+ _ -> gen_server2 :call (? SERVER , {get_client_state , Pid })
656
+ end .
657
+
625
658
% %----------------------------------------------------------------------------
626
659
% % Internal functions
627
660
% %----------------------------------------------------------------------------
@@ -1125,13 +1158,13 @@ handle_call({open, Pid, Requested, EldestUnusedSince}, From,
1125
1158
case needs_reduce (State # fhc_state { open_count = Count + Requested }) of
1126
1159
true -> case ets :lookup (Clients , Pid ) of
1127
1160
[# cstate { opened = 0 }] ->
1128
- true = ets : update_element (
1161
+ _ = safe_ets_update_element (
1129
1162
Clients , Pid , {# cstate .blocked , true }),
1130
1163
{noreply ,
1131
1164
reduce (State # fhc_state {
1132
1165
open_pending = pending_in (Item , Pending ) })};
1133
1166
[# cstate { opened = Opened }] ->
1134
- true = ets : update_element (
1167
+ _ = safe_ets_update_element (
1135
1168
Clients , Pid ,
1136
1169
{# cstate .pending_closes , Opened }),
1137
1170
{reply , close , State }
@@ -1147,7 +1180,7 @@ handle_call({obtain, N, Type, Pid}, From,
1147
1180
Item = # pending { kind = {obtain , Type }, pid = Pid ,
1148
1181
requested = N , from = From },
1149
1182
Enqueue = fun () ->
1150
- true = ets : update_element (Clients , Pid ,
1183
+ _ = safe_ets_update_element (Clients , Pid ,
1151
1184
{# cstate .blocked , true }),
1152
1185
set_obtain_state (Type , pending ,
1153
1186
pending_in (Item , Pending ), State )
@@ -1175,12 +1208,21 @@ handle_call(get_limit, _From, State = #fhc_state { limit = Limit }) ->
1175
1208
{reply , Limit , State };
1176
1209
1177
1210
handle_call ({info , Items }, _From , State ) ->
1178
- {reply , infos (Items , State ), State }.
1211
+ {reply , infos (Items , State ), State };
1212
+
1213
+ handle_call (list_elders , _From , State = # fhc_state { elders = Elders }) ->
1214
+ {reply , ets :tab2list (Elders ), State };
1215
+
1216
+ handle_call (list_clients , _From , State = # fhc_state { clients = Clients }) ->
1217
+ {reply , ets :tab2list (Clients ), State };
1218
+
1219
+ handle_call ({get_client_state , ID }, _From , State = # fhc_state { clients = Clients }) ->
1220
+ {reply , ets :lookup (Clients , ID ), State }.
1179
1221
1180
1222
handle_cast ({register_callback , Pid , MFA },
1181
1223
State = # fhc_state { clients = Clients }) ->
1182
1224
ok = track_client (Pid , Clients ),
1183
- true = ets : update_element (Clients , Pid , {# cstate .callback , MFA }),
1225
+ _ = safe_ets_update_element (Clients , Pid , {# cstate .callback , MFA }),
1184
1226
{noreply , State };
1185
1227
1186
1228
handle_cast ({update , Pid , EldestUnusedSince },
@@ -1201,7 +1243,7 @@ handle_cast({close, Pid, EldestUnusedSince},
1201
1243
undefined -> ets :delete (Elders , Pid );
1202
1244
_ -> ets :insert (Elders , {Pid , EldestUnusedSince })
1203
1245
end ,
1204
- ets : update_counter (Clients , Pid , {# cstate .pending_closes , - 1 , 0 , 0 }),
1246
+ safe_ets_update_counter (Clients , Pid , {# cstate .pending_closes , - 1 , 0 , 0 }),
1205
1247
{noreply , adjust_alarm (State , process_pending (
1206
1248
update_counts (open , Pid , - 1 , State )))};
1207
1249
@@ -1227,7 +1269,15 @@ handle_cast({set_reservation, N, Type, Pid},
1227
1269
{noreply , case needs_reduce (NewState ) of
1228
1270
true -> reduce (NewState );
1229
1271
false -> adjust_alarm (State , NewState )
1230
- end }.
1272
+ end };
1273
+
1274
+ handle_cast ({clear_metrics_of , Pid },
1275
+ State = # fhc_state { elders = Elders , clients = Clients }) ->
1276
+ ets :delete (Elders , Pid ),
1277
+ ets :delete (Clients , Pid ),
1278
+ safe_ets_update_counter (Clients , Pid , {# cstate .pending_closes , - 1 , 0 , 0 }),
1279
+ {noreply , adjust_alarm (State , process_pending (
1280
+ update_counts (open , Pid , - 1 , State )))}.
1231
1281
1232
1282
handle_info (check_counts , State ) ->
1233
1283
{noreply , maybe_reduce (State # fhc_state { timer_ref = undefined })};
@@ -1400,37 +1450,42 @@ run_pending_item(#pending { kind = Kind,
1400
1450
from = From },
1401
1451
State = # fhc_state { clients = Clients }) ->
1402
1452
gen_server2 :reply (From , ok ),
1403
- true = ets : update_element (Clients , Pid , {# cstate .blocked , false }),
1453
+ safe_ets_update_element (Clients , Pid , {# cstate .blocked , false }),
1404
1454
update_counts (Kind , Pid , Requested , State ).
1405
1455
1406
1456
update_counts (open , Pid , Delta ,
1407
1457
State = # fhc_state { open_count = OpenCount ,
1408
1458
clients = Clients }) ->
1409
- ets :update_counter (Clients , Pid , {# cstate .opened , Delta }),
1459
+ safe_ets_update_counter (Clients , Pid , {# cstate .opened , Delta },
1460
+ fun () -> rabbit_log :warning (" FHC: failed to update counter 'opened', client pid: ~p " , [Pid ]) end ),
1410
1461
State # fhc_state { open_count = OpenCount + Delta };
1411
1462
update_counts ({obtain , file }, Pid , Delta ,
1412
1463
State = # fhc_state {obtain_count_file = ObtainCountF ,
1413
1464
clients = Clients }) ->
1414
- ets :update_counter (Clients , Pid , {# cstate .obtained_file , Delta }),
1465
+ safe_ets_update_counter (Clients , Pid , {# cstate .obtained_file , Delta },
1466
+ fun () -> rabbit_log :warning (" FHC: failed to update counter 'obtained_file', client pid: ~p " , [Pid ]) end ),
1415
1467
State # fhc_state { obtain_count_file = ObtainCountF + Delta };
1416
1468
update_counts ({obtain , socket }, Pid , Delta ,
1417
1469
State = # fhc_state {obtain_count_socket = ObtainCountS ,
1418
1470
clients = Clients }) ->
1419
- ets :update_counter (Clients , Pid , {# cstate .obtained_socket , Delta }),
1471
+ safe_ets_update_counter (Clients , Pid , {# cstate .obtained_socket , Delta },
1472
+ fun () -> rabbit_log :warning (" FHC: failed to update counter 'obtained_socket', client pid: ~p " , [Pid ]) end ),
1420
1473
State # fhc_state { obtain_count_socket = ObtainCountS + Delta };
1421
1474
update_counts ({reserve , file }, Pid , NewReservation ,
1422
1475
State = # fhc_state {reserve_count_file = ReserveCountF ,
1423
1476
clients = Clients }) ->
1424
1477
[# cstate {reserved_file = R }] = ets :lookup (Clients , Pid ),
1425
1478
Delta = NewReservation - R ,
1426
- ets :update_counter (Clients , Pid , {# cstate .reserved_file , Delta }),
1479
+ safe_ets_update_counter (Clients , Pid , {# cstate .reserved_file , Delta },
1480
+ fun () -> rabbit_log :warning (" FHC: failed to update counter 'reserved_file', client pid: ~p " , [Pid ]) end ),
1427
1481
State # fhc_state { reserve_count_file = ReserveCountF + Delta };
1428
1482
update_counts ({reserve , socket }, Pid , NewReservation ,
1429
1483
State = # fhc_state {reserve_count_socket = ReserveCountS ,
1430
1484
clients = Clients }) ->
1431
1485
[# cstate {reserved_file = R }] = ets :lookup (Clients , Pid ),
1432
1486
Delta = NewReservation - R ,
1433
- ets :update_counter (Clients , Pid , {# cstate .reserved_socket , Delta }),
1487
+ safe_ets_update_counter (Clients , Pid , {# cstate .reserved_socket , Delta },
1488
+ fun () -> rabbit_log :warning (" FHC: failed to update counter 'reserved_socket', client pid: ~p " , [Pid ]) end ),
1434
1489
State # fhc_state { reserve_count_socket = ReserveCountS + Delta }.
1435
1490
1436
1491
maybe_reduce (State ) ->
@@ -1521,7 +1576,7 @@ notify(Clients, Required, [#cstate{ pid = Pid,
1521
1576
callback = {M , F , A },
1522
1577
opened = Opened } | Notifications ]) ->
1523
1578
apply (M , F , A ++ [0 ]),
1524
- ets : update_element (Clients , Pid , {# cstate .pending_closes , Opened }),
1579
+ safe_ets_update_element (Clients , Pid , {# cstate .pending_closes , Opened }),
1525
1580
notify (Clients , Required - Opened , Notifications ).
1526
1581
1527
1582
track_client (Pid , Clients ) ->
0 commit comments