+
+/* Sweep for expired communities/realms/memberships. */
+TRP_RC trps_sweep_ctable(TRPS_INSTANCE *trps)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ struct timespec sweep_time={0,0};
+ struct timespec tmp = {0};
+ TR_COMM_MEMB *memb=NULL;
+ TR_COMM_ITER *iter=NULL;
+ TRP_RC rc=TRP_ERROR;
+
+ /* use a single time for the entire sweep */
+ if (0!=clock_gettime(TRP_CLOCK, &sweep_time)) {
+ tr_err("trps_sweep_ctable: could not read realtime clock.");
+ sweep_time.tv_sec=0;
+ sweep_time.tv_nsec=0;
+ goto cleanup;
+ }
+
+ /* iterate all memberships */
+ iter=tr_comm_iter_new(tmp_ctx);
+ if (iter==NULL) {
+ tr_err("trps_sweep_ctable: unable to allocate iterator.");
+ rc=TRP_NOMEM;
+ goto cleanup;
+ }
+ for (memb=tr_comm_memb_iter_all_first(iter, trps->ctable);
+ memb!=NULL;
+ memb=tr_comm_memb_iter_all_next(iter)) {
+ if (tr_comm_memb_get_origin(memb)==NULL)
+ continue; /* do not expire local entries */
+
+ if (tr_comm_memb_is_expired(memb, &sweep_time)) {
+ if (tr_comm_memb_get_times_expired(memb)>0) {
+ /* Already expired once; flush. */
+ tr_debug("trps_sweep_ctable: flushing expired community membership (%.*s in %.*s, origin %.*s, expired %s).",
+ tr_comm_memb_get_realm_id(memb)->len, tr_comm_memb_get_realm_id(memb)->buf,
+ tr_comm_get_id(tr_comm_memb_get_comm(memb))->len, tr_comm_get_id(tr_comm_memb_get_comm(memb))->buf,
+ tr_comm_memb_get_origin(memb)->len, tr_comm_memb_get_origin(memb)->buf,
+ timespec_to_str(tr_comm_memb_get_expiry_realtime(memb, &tmp)));
+ tr_comm_table_remove_memb(trps->ctable, memb);
+ tr_comm_memb_free(memb);
+ } else {
+ /* This is the first expiration. Note this and reset the expiry time. */
+ tr_comm_memb_expire(memb);
+ trps_compute_expiry(trps, tr_comm_memb_get_interval(memb), tr_comm_memb_get_expiry(memb));
+ tr_debug("trps_sweep_ctable: community membership expired at %s, resetting expiry to %s (%.*s in %.*s, origin %.*s).",
+ timespec_to_str(tr_clock_convert(TRP_CLOCK, &sweep_time, CLOCK_REALTIME, &tmp)),
+ timespec_to_str(tr_comm_memb_get_expiry_realtime(memb, &tmp)),
+ tr_comm_memb_get_realm_id(memb)->len, tr_comm_memb_get_realm_id(memb)->buf,
+ tr_comm_get_id(tr_comm_memb_get_comm(memb))->len, tr_comm_get_id(tr_comm_memb_get_comm(memb))->buf,
+ tr_comm_memb_get_origin(memb)->len, tr_comm_memb_get_origin(memb)->buf);
+ }
+ }
+ }
+
+ /* get rid of any unreferenced realms, etc */
+ tr_comm_table_sweep(trps->ctable);
+
+cleanup:
+ talloc_free(tmp_ctx);
+ return rc;
+}
+