From: František Dvořák Date: Fri, 30 Jan 2009 18:57:21 +0000 (+0000) Subject: Handle possible race condition when refreshing/rebinding of the expired notification... X-Git-Tag: glite-lb_R_2_0_1_3~1 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=d2b274be3f80fe3bc470cc34da12925fa3bcaff2;p=jra1mw.git Handle possible race condition when refreshing/rebinding of the expired notification (dropping code refactored to the separate function). Cosmetic error in the internal notification API on server. --- diff --git a/org.glite.lb.server/src/lb_proto.c b/org.glite.lb.server/src/lb_proto.c index f171438..7a07549 100644 --- a/org.glite.lb.server/src/lb_proto.c +++ b/org.glite.lb.server/src/lb_proto.c @@ -70,7 +70,7 @@ extern int edg_wll_NotifChangeServer(edg_wll_Context, edg_wll_NotifChangeOp); extern int edg_wll_NotifRefreshServer(edg_wll_Context, const edg_wll_NotifId, time_t *); -extern int edg_wll_NotifDropServer(edg_wll_Context, edg_wll_NotifId *); +extern int edg_wll_NotifDropServer(edg_wll_Context, edg_wll_NotifId); diff --git a/org.glite.lb.server/src/notification.c b/org.glite.lb.server/src/notification.c index c495381..756098d 100644 --- a/org.glite.lb.server/src/notification.c +++ b/org.glite.lb.server/src/notification.c @@ -28,6 +28,8 @@ static int update_notif(edg_wll_Context, const edg_wll_NotifId, static int get_indexed_cols(edg_wll_Context,char const *,edg_wll_QueryRec **,char **); static void adjust_validity(edg_wll_Context,time_t *); +static int drop_notif_request(edg_wll_Context, const edg_wll_NotifId); +static int check_notif_age(edg_wll_Context, const edg_wll_NotifId); int edg_wll_NotifNewServer( @@ -191,6 +193,11 @@ int edg_wll_NotifBindServer( if ( check_notif_request(ctx, nid, NULL) ) goto rollback; + if ( check_notif_age(ctx, nid) ) { + drop_notif_request(ctx, nid); + goto rollback; + } + /* Format time of validity */ @@ -259,6 +266,11 @@ int edg_wll_NotifChangeServer( if ( check_notif_request(ctx, nid, NULL) ) goto rollback; + if ( check_notif_age(ctx, nid) ) { + drop_notif_request(ctx, nid); + goto rollback; + } + switch ( op ) { case EDG_WLL_NOTIF_REPLACE: @@ -355,6 +367,11 @@ int edg_wll_NotifRefreshServer( if ( check_notif_request(ctx, nid, NULL) ) goto rollback; + if ( check_notif_age(ctx, nid) ) { + drop_notif_request(ctx, nid); + goto rollback; + } + /* Format time of validity */ @@ -382,45 +399,19 @@ err: int edg_wll_NotifDropServer( edg_wll_Context ctx, - edg_wll_NotifId *nid) + edg_wll_NotifId nid) { - char *nid_s = NULL, - *stmt = NULL; - - do { if (edg_wll_Transaction(ctx) != 0) goto err; if ( check_notif_request(ctx, nid, NULL) ) goto rollback; - if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) ) + if ( drop_notif_request(ctx, nid) ) goto rollback; - trio_asprintf(&stmt, "delete from notif_registrations where notifid='%|Ss'", nid_s); - if ( edg_wll_ExecSQL(ctx, stmt, NULL) < 0 ) - goto rollback; - free(stmt); - trio_asprintf(&stmt, "delete from notif_jobs where notifid='%|Ss'", nid_s); - if ( edg_wll_ExecSQL(ctx, stmt, NULL) < 0 ) - goto rollback; - edg_wll_NotifCancelRegId(ctx, nid); - if (edg_wll_Error(ctx, NULL, NULL) == ECONNREFUSED) { - /* Let notification erase from DB, - * on notif-IL side it will be autopurged later anyway */ - - fprintf(stderr,"[%d] edg_wll_NotifDropServer() - NotifID found and dropped,"\ - " however, connection to notif-IL was refused (notif-IL not running?)\n", getpid()); - syslog(LOG_INFO,"edg_wll_NotifDropServer() - NotifID found and dropped,"\ - " however, connection to notif-IL was refused (notif-IL not running?)"); - - edg_wll_ResetError(ctx); - } - rollback: - free(nid_s); nid_s = NULL; - free(stmt); stmt = NULL; - + ; } while (edg_wll_TransNeedRetry(ctx)); err: @@ -521,6 +512,7 @@ static int check_notif_request( edg_wll_SetError(ctx, ENOENT, "Unknown notification ID"); else if ( ret > 0 ) edg_wll_SetError(ctx, EPERM, "Only owner could access the notification"); + goto cleanup; } cleanup: @@ -764,3 +756,76 @@ static void adjust_validity(edg_wll_Context ctx,time_t *valid) *valid = now + ctx->notifDurationMax; } +static int drop_notif_request(edg_wll_Context ctx, const edg_wll_NotifId nid) { + char *nid_s = NULL, + *stmt = NULL, + *errDesc; + int errCode; + + errCode = edg_wll_Error(ctx, NULL, &errDesc); + + if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) ) + goto rollback; + + trio_asprintf(&stmt, "delete from notif_registrations where notifid='%|Ss'", nid_s); + if ( edg_wll_ExecSQL(ctx, stmt, NULL) < 0 ) + goto rollback; + free(stmt); + trio_asprintf(&stmt, "delete from notif_jobs where notifid='%|Ss'", nid_s); + if ( edg_wll_ExecSQL(ctx, stmt, NULL) < 0 ) + goto rollback; + edg_wll_NotifCancelRegId(ctx, nid); + if (edg_wll_Error(ctx, NULL, NULL) == ECONNREFUSED) { + /* Let notification erase from DB, + * on notif-IL side it will be autopurged later anyway */ + + fprintf(stderr,"[%d] edg_wll_NotifDropServer() - NotifID found and dropped,"\ + " however, connection to notif-IL was refused (notif-IL not running?)\n", getpid()); + syslog(LOG_INFO,"edg_wll_NotifDropServer() - NotifID found and dropped,"\ + " however, connection to notif-IL was refused (notif-IL not running?)"); + + edg_wll_ResetError(ctx); + } + +rollback: + free(nid_s); nid_s = NULL; + free(stmt); stmt = NULL; + /* take precedence to previous error */ + if (errCode || errDesc) { + edg_wll_SetError(ctx, errCode, errDesc); + free(errDesc); + } + + return edg_wll_Error(ctx, NULL, NULL); +} + +static int check_notif_age(edg_wll_Context ctx, const edg_wll_NotifId nid) { + time_t now = time(NULL); + char *time_s = NULL, + *nid_s = NULL, + *q = NULL; + int ret; + + if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) ) + goto cleanup; + + glite_lbu_TimeToDB(now, &time_s); + if ( !time_s ) + { + edg_wll_SetError(ctx, errno, NULL); + goto cleanup; + } + + trio_asprintf(&q, "select notifid from notif_registrations WHERE notifid='%|Ss' AND valid < %s", nid_s, time_s); + if ( (ret = edg_wll_ExecSQL(ctx, q, NULL)) < 0 ) + goto cleanup; + + if (ret > 0) + edg_wll_SetError(ctx, EINVAL, "Notification expired."); + +cleanup: + free(q); + free(nid_s); + free(time_s); + return edg_wll_Error(ctx, NULL, NULL); +}