summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp')
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp387
1 files changed, 387 insertions, 0 deletions
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp b/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp
new file mode 100644
index 0000000..7407b4e
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp
@@ -0,0 +1,387 @@
+// Copyright 1997-2022 The OpenLDAP Foundation, All Rights Reserved.
+// COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+
+// (c) Copyright 1999-2001 TimesTen Performance Software. All rights reserved.
+
+//// Note: This file was contributed by Sam Drake of TimesTen Performance
+//// Software for use and redistribution as an integral part of
+//// OpenLDAP Software. -Kdz
+
+#include <stdlib.h>
+
+#include <TTConnectionPool.h>
+#include <TTConnection.h>
+#include <TTCmd.h>
+#include <TTXla.h>
+
+#include <signal.h>
+
+TTConnectionPool pool;
+TTXlaConnection conn;
+TTConnection conn2;
+TTCmd assignDn_ru;
+TTCmd getNullDNs;
+
+//----------------------------------------------------------------------
+// This class contains all the logic to be implemented whenever
+// the SCOTT.MYDATA table is changed. This is the table that is
+// created by "sample.cpp", one of the other TTClasses demos.
+// That application should be executed before this one in order to
+// create and populate the table.
+//----------------------------------------------------------------------
+
+class LDAPEntriesHandler: public TTXlaTableHandler {
+private:
+ // Definition of the columns in the table
+ int Id;
+ int Dn;
+ int Oc_map_id;
+ int Parent;
+ int Keyval;
+ int Dn_ru;
+
+protected:
+
+public:
+ LDAPEntriesHandler(TTXlaConnection& conn, const char* ownerP, const char* nameP);
+ ~LDAPEntriesHandler();
+
+ virtual void HandleDelete(ttXlaUpdateDesc_t*);
+ virtual void HandleInsert(ttXlaUpdateDesc_t*);
+ virtual void HandleUpdate(ttXlaUpdateDesc_t*);
+
+ static void ReverseAndUpper(char* dnP, int id, bool commit=true);
+
+};
+
+LDAPEntriesHandler::LDAPEntriesHandler(TTXlaConnection& conn,
+ const char* ownerP, const char* nameP) :
+ TTXlaTableHandler(conn, ownerP, nameP)
+{
+ Id = Dn = Oc_map_id = Parent = Keyval = Dn_ru = -1;
+
+ // We are looking for several particular named columns. We need to get
+ // the ordinal position of the columns by name for later use.
+
+ Id = tbl.getColNumber("ID");
+ if (Id < 0) {
+ cerr << "target table has no 'ID' column" << endl;
+ exit(1);
+ }
+ Dn = tbl.getColNumber("DN");
+ if (Dn < 0) {
+ cerr << "target table has no 'DN' column" << endl;
+ exit(1);
+ }
+ Oc_map_id = tbl.getColNumber("OC_MAP_ID");
+ if (Oc_map_id < 0) {
+ cerr << "target table has no 'OC_MAP_ID' column" << endl;
+ exit(1);
+ }
+ Parent = tbl.getColNumber("PARENT");
+ if (Parent < 0) {
+ cerr << "target table has no 'PARENT' column" << endl;
+ exit(1);
+ }
+ Keyval = tbl.getColNumber("KEYVAL");
+ if (Keyval < 0) {
+ cerr << "target table has no 'KEYVAL' column" << endl;
+ exit(1);
+ }
+ Dn_ru = tbl.getColNumber("DN_RU");
+ if (Dn_ru < 0) {
+ cerr << "target table has no 'DN_RU' column" << endl;
+ exit(1);
+ }
+
+}
+
+LDAPEntriesHandler::~LDAPEntriesHandler()
+{
+
+}
+
+void LDAPEntriesHandler::ReverseAndUpper(char* dnP, int id, bool commit)
+{
+ TTStatus stat;
+ char dn_rn[512];
+ int i;
+ int j;
+
+ // Reverse and upper case the given DN
+
+ for ((j=0, i = strlen(dnP)-1); i > -1; (j++, i--)) {
+ dn_rn[j] = toupper(*(dnP+i));
+ }
+ dn_rn[j] = '\0';
+
+
+ // Update the database
+
+ try {
+ assignDn_ru.setParam(1, (char*) &dn_rn[0]);
+ assignDn_ru.setParam(2, id);
+ assignDn_ru.Execute(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error updating id " << id << " ('" << dnP << "' to '"
+ << dn_rn << "'): " << stat;
+ exit(1);
+ }
+
+ // Commit the transaction
+
+ if (commit) {
+ try {
+ conn2.Commit(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error committing update: " << stat;
+ exit(1);
+ }
+ }
+
+}
+
+
+
+void LDAPEntriesHandler::HandleInsert(ttXlaUpdateDesc_t* p)
+{
+ char* dnP;
+ int id;
+
+ row.Get(Dn, &dnP);
+ cerr << "DN '" << dnP << "': Inserted ";
+ row.Get(Id, &id);
+
+ ReverseAndUpper(dnP, id);
+
+}
+
+void LDAPEntriesHandler::HandleUpdate(ttXlaUpdateDesc_t* p)
+{
+ char* newDnP;
+ char* oldDnP;
+ char oDn[512];
+ int id;
+
+ // row is 'old'; row2 is 'new'
+ row.Get(Dn, &oldDnP);
+ strcpy(oDn, oldDnP);
+ row.Get(Id, &id);
+ row2.Get(Dn, &newDnP);
+
+ cerr << "old DN '" << oDn << "' / new DN '" << newDnP << "' : Updated ";
+
+ if (strcmp(oDn, newDnP) != 0) {
+ // The DN field changed, update it
+ cerr << "(new DN: '" << newDnP << "')";
+ ReverseAndUpper(newDnP, id);
+ }
+ else {
+ // The DN field did NOT change, leave it alone
+ }
+
+ cerr << endl;
+
+}
+
+void LDAPEntriesHandler::HandleDelete(ttXlaUpdateDesc_t* p)
+{
+ char* dnP;
+
+ row.Get(Dn, &dnP);
+ cerr << "DN '" << dnP << "': Deleted ";
+}
+
+
+
+
+//----------------------------------------------------------------------
+
+int pleaseStop = 0;
+
+extern "C" {
+ void
+ onintr(int sig)
+ {
+ pleaseStop = 1;
+ cerr << "Stopping...\n";
+ }
+};
+
+//----------------------------------------------------------------------
+
+int
+main(int argc, char* argv[])
+{
+
+ char* ownerP;
+
+ TTXlaTableList list(&conn); // List of tables to monitor
+
+ // Handlers, one for each table we want to monitor
+
+ LDAPEntriesHandler* sampP = NULL;
+
+ // Misc stuff
+
+ TTStatus stat;
+
+ ttXlaUpdateDesc_t ** arry;
+
+ int records;
+
+ SQLUBIGINT oldsize;
+ int j;
+
+ if (argc < 2) {
+ cerr << "syntax: " << argv[0] << " <username>" << endl;
+ exit(3);
+ }
+
+ ownerP = argv[1];
+
+ signal(SIGINT, onintr); /* signal for CTRL-C */
+#ifdef _WIN32
+ signal(SIGBREAK, onintr); /* signal for CTRL-BREAK */
+#endif
+
+ // Before we do anything related to XLA, first we connect
+ // to the database. This is the connection we will use
+ // to perform non-XLA operations on the tables.
+
+ try {
+ cerr << "Connecting..." << endl;
+
+ conn2.Connect("DSN=ldap_tt", stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error connecting to TimesTen: " << stat;
+ exit(1);
+ }
+
+ try {
+ assignDn_ru.Prepare(&conn2,
+ "update ldap_entries set dn_ru=? where id=?",
+ "", stat);
+ getNullDNs.Prepare(&conn2,
+ "select dn, id from ldap_entries "
+ "where dn_ru is null "
+ "for update",
+ "", stat);
+ conn2.Commit(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error preparing update: " << stat;
+ exit(1);
+ }
+
+ // If there are any entries with a NULL reversed/upper cased DN,
+ // fix them now.
+
+ try {
+ cerr << "Fixing NULL reversed DNs" << endl;
+ getNullDNs.Execute(stat);
+ for (int k = 0;; k++) {
+ getNullDNs.FetchNext(stat);
+ if (stat.rc == SQL_NO_DATA_FOUND) break;
+ char* dnP;
+ int id;
+ getNullDNs.getColumn(1, &dnP);
+ getNullDNs.getColumn(2, &id);
+ // cerr << "Id " << id << ", Dn '" << dnP << "'" << endl;
+ LDAPEntriesHandler::ReverseAndUpper(dnP, id, false);
+ if (k % 1000 == 0)
+ cerr << ".";
+ }
+ getNullDNs.Close(stat);
+ conn2.Commit(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error updating NULL rows: " << stat;
+ exit(1);
+ }
+
+
+ // Go ahead and start up the change monitoring application
+
+ cerr << "Starting change monitoring..." << endl;
+ try {
+ conn.Connect("DSN=ldap_tt", stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error connecting to TimesTen: " << stat;
+ exit(1);
+ }
+
+ /* set and configure size of buffer */
+ conn.setXlaBufferSize((SQLUBIGINT) 1000000, &oldsize, stat);
+ if (stat.rc) {
+ cerr << "Error setting buffer size " << stat << endl;
+ exit(1);
+ }
+
+ // Make a handler to process changes to the MYDATA table and
+ // add the handler to the list of all handlers
+
+ sampP = new LDAPEntriesHandler(conn, ownerP, "ldap_entries");
+ if (!sampP) {
+ cerr << "Could not create LDAPEntriesHandler" << endl;
+ exit(3);
+ }
+ list.add(sampP);
+
+ // Enable transaction logging for the table we're interested in
+
+ sampP->EnableTracking(stat);
+
+ // Get updates. Dispatch them to the appropriate handler.
+ // This loop will handle updates to all the tables.
+
+ while (pleaseStop == 0) {
+ conn.fetchUpdates(&arry, 1000, &records, stat);
+ if (stat.rc) {
+ cerr << "Error fetching updates" << stat << endl;
+ exit(1);
+ }
+
+ // Interpret the updates
+
+ for(j=0;j < records;j++){
+ ttXlaUpdateDesc_t *p;
+
+ p = arry[j];
+
+ list.HandleChange(p, stat);
+
+ } // end for each record fetched
+
+ if (records) {
+ cerr << "Processed " << records << " records\n";
+ }
+
+ if (records == 0) {
+#ifdef _WIN32
+ Sleep(250);
+#else
+ struct timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 250000; // .25 seconds
+ select(0, NULL, NULL, NULL, &t);
+#endif
+ }
+ } // end while pleasestop == 0
+
+
+ // When we get to here, the program is exiting.
+
+ list.del(sampP); // Take the table out of the list
+ delete sampP;
+
+ conn.setXlaBufferSize(oldsize, NULL, stat);
+
+ return 0;
+
+}
+