abandon.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* abandon.c - decode and handle an ldap abandon operation */
  13. /*
  14. * Copyright (c) 1995 Regents of the University of Michigan.
  15. * All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms are permitted
  18. * provided that this notice is preserved and that due credit is given
  19. * to the University of Michigan at Ann Arbor. The name of the University
  20. * may not be used to endorse or promote products derived from this
  21. * software without specific prior written permission. This software
  22. * is provided ``as is'' without express or implied warranty.
  23. */
  24. #include <stdio.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include "slap.h"
  28. void
  29. do_abandon( Slapi_PBlock *pb )
  30. {
  31. int err, suppressed_by_plugin = 0;
  32. ber_int_t id;
  33. Operation *o;
  34. BerElement *ber = pb->pb_op->o_ber;
  35. LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
  36. /*
  37. * Parse the abandon request. It looks like this:
  38. *
  39. * AbandonRequest := MessageID
  40. */
  41. if ( ber_scanf( ber, "i", &id ) == LBER_ERROR ) {
  42. LDAPDebug( LDAP_DEBUG_ANY,
  43. "ber_scanf failed (op=Abandon; params=ID)\n",
  44. 0, 0 ,0 );
  45. return;
  46. }
  47. slapi_pblock_set( pb, SLAPI_ABANDON_MSGID, &id );
  48. /*
  49. * in LDAPv3 there can be optional control extensions on
  50. * the end of an LDAPMessage. we need to read them in and
  51. * pass them to the backend.
  52. */
  53. if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
  54. LDAPDebug( LDAP_DEBUG_ANY,
  55. "get_ldapmessage_controls failed: %d (%s) (op=Abandon)\n",
  56. err, ldap_err2string( err ), 0);
  57. /* LDAP does not allow any response to an abandon */
  58. return;
  59. }
  60. LDAPDebug( LDAP_DEBUG_ARGS, "do_abandon: id %d\n", id, 0 ,0 );
  61. /*
  62. * find the operation being abandoned and set the o_abandon
  63. * flag. We don't allow the operation to abandon itself.
  64. * It's up to the backend to periodically check this
  65. * flag and abort the operation at a convenient time.
  66. */
  67. PR_EnterMonitor(pb->pb_conn->c_mutex);
  68. for ( o = pb->pb_conn->c_ops; o != NULL; o = o->o_next ) {
  69. if ( o->o_msgid == id && o != pb->pb_op)
  70. break;
  71. }
  72. if ( o != NULL ) {
  73. const Slapi_DN *ts = NULL;
  74. /*
  75. * call the pre-abandon plugins. if they succeed, call
  76. * the backend abandon function. then call the post-abandon
  77. * plugins.
  78. */
  79. /* ONREPL - plugins should be passed some information about abandoned operation */
  80. /* target spec and abandoned operation type are used to decide which plugins
  81. are applicable for the operation */
  82. ts = operation_get_target_spec (o);
  83. if (ts) {
  84. operation_set_target_spec (pb->pb_op, ts);
  85. } else {
  86. LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon: no target spec of abandoned operation\n", 0,0,0);
  87. }
  88. operation_set_abandoned_op (pb->pb_op, o->o_abandoned_op);
  89. if ( plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_ABANDON_FN ) == 0 ) {
  90. int rc = 0;
  91. if ( o->o_status != SLAPI_OP_STATUS_RESULT_SENT ) {
  92. o->o_status = SLAPI_OP_STATUS_ABANDONED;
  93. } else {
  94. o = NULL; /* nothing was abandoned */
  95. }
  96. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &rc );
  97. plugin_call_plugins( pb, SLAPI_PLUGIN_POST_ABANDON_FN );
  98. } else {
  99. suppressed_by_plugin = 1;
  100. }
  101. } else {
  102. LDAPDebug0Args(LDAP_DEBUG_TRACE, "do_abandon: op not found\n");
  103. }
  104. if ( 0 == pagedresults_free_one_msgid_nolock(pb->pb_conn, id) ) {
  105. slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64
  106. " op=%d ABANDON targetop=Simple Paged Results msgid=%d\n",
  107. pb->pb_conn->c_connid, pb->pb_op->o_opid, id );
  108. } else if ( NULL == o ) {
  109. slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ABANDON"
  110. " targetop=NOTFOUND msgid=%d\n",
  111. pb->pb_conn->c_connid, pb->pb_op->o_opid, id );
  112. } else if ( suppressed_by_plugin ) {
  113. slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ABANDON"
  114. " targetop=SUPPRESSED-BY-PLUGIN msgid=%d\n",
  115. pb->pb_conn->c_connid, pb->pb_op->o_opid, id );
  116. } else {
  117. slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ABANDON"
  118. " targetop=%d msgid=%d nentries=%d etime=%ld\n",
  119. pb->pb_conn->c_connid, pb->pb_op->o_opid, o->o_opid, id,
  120. o->o_results.r.r_search.nentries, current_time() - o->o_time );
  121. }
  122. PR_ExitMonitor(pb->pb_conn->c_mutex);
  123. /*
  124. * Wake up the persistent searches, so they
  125. * can notice if they've been abandoned.
  126. */
  127. ps_wakeup_all();
  128. }