time_t last_clear; //!< So we only do it once a second.
char const *allocate_begin; //!< SQL query to begin.
char const *allocate_clear; //!< SQL query to clear an IP.
+ uint32_t allocate_clear_timeout; //!< Number of second between two allocate_clear SQL query
char const *allocate_find; //!< SQL query to find an unused IP.
char const *allocate_update; //!< SQL query to mark an IP as used.
char const *allocate_commit; //!< SQL query to commit.
{ "allocate-clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_clear), NULL },
{ "allocate_clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT , rlm_sqlippool_t, allocate_clear), "" },
+ { "allocate-clear-timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_clear_timeout), NULL },
+ { "allocate_clear_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_sqlippool_t, allocate_clear_timeout), "1" },
+
{ "allocate-find", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_find), NULL },
{ "allocate_find", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, allocate_find), "" },
VALUE_PAIR *vp;
rlm_sql_handle_t *handle;
time_t now;
+ uint32_t diff_time;
/*
* If there is already an attribute in the reply do nothing
* race conditions for the check, but so what. The
* actual work is protected by a transaction. The idea
* here is that if we're allocating 100 IPs a second,
- * we're only do 1 CLEAR per second.
+ * we're only do 1 CLEAR per allocate_clear_timeout.
+ * This will avoid having several queries to deadlock and blocking all
+ * the sqlippool module.
*/
now = time(NULL);
- if (inst->allocate_clear && *inst->allocate_clear && (inst->last_clear < now)) {
+ diff_time = difftime(now, inst->last_clear);
+ if (inst->allocate_clear && *inst->allocate_clear && diff_time >= inst->allocate_clear_timeout) {
inst->last_clear = now;
DO_PART(allocate_begin);