]> git.sur5r.net Git - openldap/commitdiff
LDAP cancel operation
authorJong Hyuk Choi <jongchoi@openldap.org>
Sat, 25 Jan 2003 00:36:50 +0000 (00:36 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Sat, 25 Jan 2003 00:36:50 +0000 (00:36 +0000)
12 files changed:
include/ldap.h
libraries/libldap/Makefile.in
libraries/libldap/cancel.c [new file with mode: 0644]
servers/slapd/Makefile.in
servers/slapd/back-bdb/search.c
servers/slapd/backend.c
servers/slapd/cancel.c [new file with mode: 0644]
servers/slapd/connection.c
servers/slapd/extended.c
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/tools/Makefile.in

index 3df4fb536ab621f16d61299519e62858c7e419d1..0686ca17c9bef66e21516dbc9ca3c47a30d7ff9c 100644 (file)
@@ -486,6 +486,17 @@ typedef struct ldapcontrol {
 #define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL  0x01
 #endif /* LDAP_CLIENT_UPDATE */
 
+/* resultCode for Cancel Response */
+#define LDAP_CANCELLED                  0x68
+#define LDAP_NO_SUCH_OPERATION          0x69
+#define LDAP_TOO_LATE                   0x6a
+#define LDAP_CANNOT_CANCEL              0x6b
+
+#define LDAP_CANCEL_NONE                0x00
+#define LDAP_CANCEL_REQ                 0x01
+#define LDAP_CANCEL_ACK                 0x02
+#define LDAP_CANCEL_NOTDONE             0x03
+
 /*
  * This structure represents both ldap messages and ldap responses.
  * These are really the same, except in the case of search responses,
index f8962fcb3fcfe0bb973c9a2e0c06f5bb978d7d09..e624abce1662cb9e9b1bc245011c9ffb1567f013 100644 (file)
@@ -16,7 +16,8 @@ SRCS  = bind.c open.c result.c error.c compare.c search.c \
        getdn.c getentry.c getattr.c getvalues.c addentry.c \
        request.c os-ip.c url.c sortctrl.c vlvctrl.c \
        init.c options.c print.c string.c util-int.c schema.c \
-       charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c
+       charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
+       cancel.c
 OBJS   = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        controls.lo messages.lo references.lo extended.lo cyrus.lo \
        modify.lo add.lo modrdn.lo delete.lo abandon.lo cache.lo \
@@ -25,7 +26,8 @@ OBJS  = bind.lo open.lo result.lo error.lo compare.lo search.lo \
        getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
        request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \
        init.lo options.lo print.lo string.lo util-int.lo schema.lo \
-       charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo
+       charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \
+       cancel.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
diff --git a/libraries/libldap/cancel.c b/libraries/libldap/cancel.c
new file mode 100644 (file)
index 0000000..6b8aeac
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+/*
+ * LDAPv3 Cancel Operation Request
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+#include "ldap_log.h"
+
+int
+ldap_cancel(
+       LDAP            *ld,
+       int             cancelid,
+       LDAPControl     **sctrls,
+       LDAPControl     **cctrls,
+       int             *msgidp )
+{
+       BerElement *cancelidber = NULL;
+       struct berval *cancelidvalp = NULL;
+       int rc;
+
+       cancelidber = ber_alloc_t( LBER_USE_DER );
+       ber_printf( cancelidber, "{i}", cancelid );
+       ber_flatten( cancelidber, &cancelidvalp );
+       rc = ldap_extended_operation( ld, LDAP_EXOP_X_CANCEL,
+                       cancelidvalp, sctrls, cctrls, msgidp );
+       ber_free( cancelidber, 1 );
+       return rc;
+}
+
+int
+ldap_cancel_s(
+       LDAP            *ld,
+       int             cancelid,
+       LDAPControl     **sctrls,
+       LDAPControl     **cctrls )
+{
+       BerElement *cancelidber = NULL;
+       struct berval *cancelidvalp = NULL;
+       int rc;
+
+       cancelidber = ber_alloc_t( LBER_USE_DER );
+       ber_printf( cancelidber, "{i}", cancelid );
+       ber_flatten( cancelidber, &cancelidvalp );
+       rc = ldap_extended_operation_s( ld, LDAP_EXOP_X_CANCEL,
+                       cancelidvalp, sctrls, cctrls, NULL, NULL );
+       ber_free( cancelidber, 1 );
+       return rc;
+}
index 97e773f031ad3713681099876c9eb7e3b4caa8c6..42d4024637ce6b4844bea89fa658c61d8a6fe3bb 100644 (file)
@@ -19,7 +19,7 @@ SRCS  = main.c daemon.c connection.c search.c filter.c add.c cr.c \
                schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
                oidm.c starttls.c index.c sets.c referral.c \
                root_dse.c sasl.c module.c suffixalias.c mra.c mods.c \
-               limits.c backglue.c operational.c matchedValues.c \
+               limits.c backglue.c operational.c matchedValues.c cancel.c \
                $(@PLAT@_SRCS)
 
 OBJS   = main.o daemon.o connection.o search.o filter.o add.o cr.o \
@@ -32,7 +32,7 @@ OBJS  = main.o daemon.o connection.o search.o filter.o add.o cr.o \
                schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
                oidm.o starttls.o index.o sets.o referral.o \
                root_dse.o sasl.o module.o suffixalias.o mra.o mods.o \
-               limits.o backglue.o operational.o matchedValues.o \
+               limits.o backglue.o operational.o matchedValues.o cancel.o \
                $(@PLAT@_OBJS)
 
 LDAP_INCDIR= ../../include -Islapi
index f85c8b5c098fc4788a12435ea7db2d3bc9d830bf..9916cdb22e4e8dbfc58eb10c2ef7af2ed855c790 100644 (file)
@@ -433,6 +433,15 @@ loop_begin:
                        goto done;
                }
 
+               if ( op->o_cancel ) {
+                       assert( op->o_cancel == LDAP_CANCEL_REQ );
+                       rc = 0;
+                       send_search_result( conn, op, LDAP_CANCELLED,
+                                       NULL, NULL, NULL, NULL, 0 );
+                       op->o_cancel = LDAP_CANCEL_ACK;
+                       goto done;
+               }
+
                /* check time limit */
                if ( tlimit != -1 && slap_get_time() > stoptime ) {
                        send_search_result( conn, op, rc = LDAP_TIMELIMIT_EXCEEDED,
index 7d3aea77e389bb45b8f9773443943d2fc808def9..6ef6f33ff6dd3fcee18b809fa3f88dc1404b566e 100644 (file)
@@ -870,6 +870,13 @@ backend_check_restrictions(
                        }
                }
 
+               {
+                       struct berval bv = BER_BVC( LDAP_EXOP_X_CANCEL );
+                       if ( bvmatch( opdata, &bv ) ) {
+                               break;
+                       }
+               }
+
                /* treat everything else as a modify */
                opflag = SLAP_RESTRICT_OP_MODIFY;
                updateop++;
diff --git a/servers/slapd/cancel.c b/servers/slapd/cancel.c
new file mode 100644 (file)
index 0000000..96bd730
--- /dev/null
@@ -0,0 +1,114 @@
+/* cancel.c - LDAP cancel extended operation */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/krb.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+
+#include <lber_pvt.h>
+#include <lutil.h>
+
+int cancel_extop(
+       Connection *conn,
+       Operation *op,
+       const char *reqoid,
+       struct berval *reqdata,
+       char **rspoid,
+       struct berval **rspdata,
+       LDAPControl ***rspctrls,
+       const char **text,
+       BerVarray *refs )
+{
+       Backend *be;
+       int rc;
+       int found = 0;
+       int opid;
+       BerElement *ber;
+
+       assert( reqoid != NULL );
+       assert( strcmp( LDAP_EXOP_X_CANCEL, reqoid ) == 0 );
+
+       if ( reqdata == NULL ) {
+               *text = "no message ID supplied";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       ber = ber_init( reqdata );
+       if ( ber == NULL ) {
+               *text = "internal error";
+               return LDAP_OTHER;
+       }
+
+       if ( ber_scanf( ber, "{i}", &opid ) == LBER_ERROR ) {
+               *text = "message ID parse failed";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       (void) ber_free( ber, 1 );
+
+       if ( opid < 0 ) {
+               *text = "message ID invalid";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+       LDAP_STAILQ_FOREACH( op, &conn->c_pending_ops, o_next ) {
+               if ( op->o_msgid == opid ) {
+                       LDAP_STAILQ_REMOVE( &conn->c_pending_ops, op, slap_op, o_next );
+                       slap_op_free( op );
+                       found = 1;
+                       break;
+               }
+       }
+       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+       if ( found )
+               return LDAP_SUCCESS;
+
+       found = 0;
+       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+       LDAP_STAILQ_FOREACH( op, &conn->c_ops, o_next ) {
+               if ( op->o_msgid == opid ) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if ( !found ) {
+               *text = "message ID not found";
+               ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+               return LDAP_NO_SUCH_OPERATION;
+       }
+
+       if ( op->o_cancel != LDAP_CANCEL_NONE ) {
+               *text = "message ID already being cancelled";
+               ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       op->o_cancel = LDAP_CANCEL_REQ;
+       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+       while ( op->o_cancel == LDAP_CANCEL_REQ ) {
+               ldap_pvt_thread_yield();
+       }
+
+       if ( op->o_cancel == LDAP_CANCEL_ACK ) {
+               rc = LDAP_SUCCESS;
+       } else {
+               rc = op->o_cancel;
+               op->o_cancel = LDAP_CANCEL_NOTDONE;
+       }
+
+       return rc;
+}
index 06abd15472585553183323f2738e229d25c35006..ba8d419836914f8517fc1f8de0bacce4c66e35fd 100644 (file)
@@ -1024,6 +1024,15 @@ operations_error:
 #endif /* SLAPD_MONITOR */
        ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
 
+       if ( arg->co_op->o_cancel == LDAP_CANCEL_REQ )
+               arg->co_op->o_cancel = LDAP_TOO_LATE;
+
+       while ( arg->co_op->o_cancel != LDAP_CANCEL_NONE &&
+               arg->co_op->o_cancel != LDAP_CANCEL_ACK  &&
+               arg->co_op->o_cancel != LDAP_CANCEL_NOTDONE ) {
+                       ldap_pvt_thread_yield();
+       }
+
        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
        conn->c_n_ops_executing--;
index b658f215de7c8232b8d0d09848394ecdb1e40920..d9e70ed4cc421787e2f75a075407e48ecb36f7d8 100644 (file)
@@ -64,6 +64,7 @@ static struct {
 #endif
        { BVC(LDAP_EXOP_MODIFY_PASSWD), passwd_extop },
        { BVC(LDAP_EXOP_X_WHO_AM_I), whoami_extop },
+       { BVC(LDAP_EXOP_X_CANCEL), cancel_extop },
        { {0,NULL}, NULL }
 };
 
index cab27a8eb880069a0c10db5769fc97a6afcf5a5a..51f1c1eb8617c56e122bbe7e94bcd84a125a2d5a 100644 (file)
@@ -474,6 +474,11 @@ LDAP_SLAPD_F (int) extops_kill LDAP_P(( void ));
 
 LDAP_SLAPD_F (struct berval *) get_supported_extop LDAP_P((int index));
 
+/*
+ *  * cancel.c
+ *   */
+LDAP_SLAPD_F ( SLAP_EXTOP_MAIN_FN ) cancel_extop;
+
 /*
  * filter.c
  */
index 9ba350adc0970d8e933daab3065723579cf1ed29..791f91f02f1cdf53b9c38b5bcf6a30892690b764 100644 (file)
@@ -1661,6 +1661,7 @@ typedef struct slap_op {
        ldap_pvt_thread_t       o_tid;  /* thread handling this op */
 
        volatile sig_atomic_t o_abandon;        /* abandon flag */
+       volatile sig_atomic_t o_cancel;         /* cancel flag */
 
        char o_do_not_cache;    /* don't cache from this op */
 
index c47e38afb4a146ed14604cc7ac0e83305d779e75..70eaff2304068f592eb544e68a301492a0cdf4da 100644 (file)
@@ -45,7 +45,8 @@ SLAPD_OBJS = ../config.o ../ch_malloc.o ../cr.o ../backend.o \
                ../entry.o ../dn.o ../filter.o ../str2filter.o ../ava.o \
                ../init.o ../controls.o ../kerberos.o ../passwd.o \
                ../index.o ../extended.o ../starttls.o ../sets.o ../mra.o \
-               ../referral.o ../backglue.o ../oidm.o ../mods.o ../operation.o
+               ../referral.o ../backglue.o ../oidm.o ../mods.o ../operation.o \
+               ../cancel.o
 
 SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o