1 // Copyright 1997-2017 The OpenLDAP Foundation, All Rights Reserved.
2 // COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4 // (c) Copyright 1999-2001 TimesTen Performance Software. All rights reserved.
6 //// Note: This file was contributed by Sam Drake of TimesTen Performance
7 //// Software for use and redistribution as an integral part of
8 //// OpenLDAP Software. -Kdz
12 #include <TTConnectionPool.h>
13 #include <TTConnection.h>
19 TTConnectionPool pool;
25 //----------------------------------------------------------------------
26 // This class contains all the logic to be implemented whenever
27 // the SCOTT.MYDATA table is changed. This is the table that is
28 // created by "sample.cpp", one of the other TTClasses demos.
29 // That application should be executed before this one in order to
30 // create and populate the table.
31 //----------------------------------------------------------------------
33 class LDAPEntriesHandler: public TTXlaTableHandler {
35 // Definition of the columns in the table
46 LDAPEntriesHandler(TTXlaConnection& conn, const char* ownerP, const char* nameP);
47 ~LDAPEntriesHandler();
49 virtual void HandleDelete(ttXlaUpdateDesc_t*);
50 virtual void HandleInsert(ttXlaUpdateDesc_t*);
51 virtual void HandleUpdate(ttXlaUpdateDesc_t*);
53 static void ReverseAndUpper(char* dnP, int id, bool commit=true);
57 LDAPEntriesHandler::LDAPEntriesHandler(TTXlaConnection& conn,
58 const char* ownerP, const char* nameP) :
59 TTXlaTableHandler(conn, ownerP, nameP)
61 Id = Dn = Oc_map_id = Parent = Keyval = Dn_ru = -1;
63 // We are looking for several particular named columns. We need to get
64 // the ordinal position of the columns by name for later use.
66 Id = tbl.getColNumber("ID");
68 cerr << "target table has no 'ID' column" << endl;
71 Dn = tbl.getColNumber("DN");
73 cerr << "target table has no 'DN' column" << endl;
76 Oc_map_id = tbl.getColNumber("OC_MAP_ID");
78 cerr << "target table has no 'OC_MAP_ID' column" << endl;
81 Parent = tbl.getColNumber("PARENT");
83 cerr << "target table has no 'PARENT' column" << endl;
86 Keyval = tbl.getColNumber("KEYVAL");
88 cerr << "target table has no 'KEYVAL' column" << endl;
91 Dn_ru = tbl.getColNumber("DN_RU");
93 cerr << "target table has no 'DN_RU' column" << endl;
99 LDAPEntriesHandler::~LDAPEntriesHandler()
104 void LDAPEntriesHandler::ReverseAndUpper(char* dnP, int id, bool commit)
111 // Reverse and upper case the given DN
113 for ((j=0, i = strlen(dnP)-1); i > -1; (j++, i--)) {
114 dn_rn[j] = toupper(*(dnP+i));
119 // Update the database
122 assignDn_ru.setParam(1, (char*) &dn_rn[0]);
123 assignDn_ru.setParam(2, id);
124 assignDn_ru.Execute(stat);
126 catch (TTStatus stat) {
127 cerr << "Error updating id " << id << " ('" << dnP << "' to '"
128 << dn_rn << "'): " << stat;
132 // Commit the transaction
138 catch (TTStatus stat) {
139 cerr << "Error committing update: " << stat;
148 void LDAPEntriesHandler::HandleInsert(ttXlaUpdateDesc_t* p)
154 cerr << "DN '" << dnP << "': Inserted ";
157 ReverseAndUpper(dnP, id);
161 void LDAPEntriesHandler::HandleUpdate(ttXlaUpdateDesc_t* p)
168 // row is 'old'; row2 is 'new'
169 row.Get(Dn, &oldDnP);
172 row2.Get(Dn, &newDnP);
174 cerr << "old DN '" << oDn << "' / new DN '" << newDnP << "' : Updated ";
176 if (strcmp(oDn, newDnP) != 0) {
177 // The DN field changed, update it
178 cerr << "(new DN: '" << newDnP << "')";
179 ReverseAndUpper(newDnP, id);
182 // The DN field did NOT change, leave it alone
189 void LDAPEntriesHandler::HandleDelete(ttXlaUpdateDesc_t* p)
194 cerr << "DN '" << dnP << "': Deleted ";
200 //----------------------------------------------------------------------
209 cerr << "Stopping...\n";
213 //----------------------------------------------------------------------
216 main(int argc, char* argv[])
221 TTXlaTableList list(&conn); // List of tables to monitor
223 // Handlers, one for each table we want to monitor
225 LDAPEntriesHandler* sampP = NULL;
231 ttXlaUpdateDesc_t ** arry;
239 cerr << "syntax: " << argv[0] << " <username>" << endl;
245 signal(SIGINT, onintr); /* signal for CTRL-C */
247 signal(SIGBREAK, onintr); /* signal for CTRL-BREAK */
250 // Before we do anything related to XLA, first we connect
251 // to the database. This is the connection we will use
252 // to perform non-XLA operations on the tables.
255 cerr << "Connecting..." << endl;
257 conn2.Connect("DSN=ldap_tt", stat);
259 catch (TTStatus stat) {
260 cerr << "Error connecting to TimesTen: " << stat;
265 assignDn_ru.Prepare(&conn2,
266 "update ldap_entries set dn_ru=? where id=?",
268 getNullDNs.Prepare(&conn2,
269 "select dn, id from ldap_entries "
270 "where dn_ru is null "
275 catch (TTStatus stat) {
276 cerr << "Error preparing update: " << stat;
280 // If there are any entries with a NULL reversed/upper cased DN,
284 cerr << "Fixing NULL reversed DNs" << endl;
285 getNullDNs.Execute(stat);
286 for (int k = 0;; k++) {
287 getNullDNs.FetchNext(stat);
288 if (stat.rc == SQL_NO_DATA_FOUND) break;
291 getNullDNs.getColumn(1, &dnP);
292 getNullDNs.getColumn(2, &id);
293 // cerr << "Id " << id << ", Dn '" << dnP << "'" << endl;
294 LDAPEntriesHandler::ReverseAndUpper(dnP, id, false);
298 getNullDNs.Close(stat);
301 catch (TTStatus stat) {
302 cerr << "Error updating NULL rows: " << stat;
307 // Go ahead and start up the change monitoring application
309 cerr << "Starting change monitoring..." << endl;
311 conn.Connect("DSN=ldap_tt", stat);
313 catch (TTStatus stat) {
314 cerr << "Error connecting to TimesTen: " << stat;
318 /* set and configure size of buffer */
319 conn.setXlaBufferSize((SQLUBIGINT) 1000000, &oldsize, stat);
321 cerr << "Error setting buffer size " << stat << endl;
325 // Make a handler to process changes to the MYDATA table and
326 // add the handler to the list of all handlers
328 sampP = new LDAPEntriesHandler(conn, ownerP, "ldap_entries");
330 cerr << "Could not create LDAPEntriesHandler" << endl;
335 // Enable transaction logging for the table we're interested in
337 sampP->EnableTracking(stat);
339 // Get updates. Dispatch them to the appropriate handler.
340 // This loop will handle updates to all the tables.
342 while (pleaseStop == 0) {
343 conn.fetchUpdates(&arry, 1000, &records, stat);
345 cerr << "Error fetching updates" << stat << endl;
349 // Interpret the updates
351 for(j=0;j < records;j++){
352 ttXlaUpdateDesc_t *p;
356 list.HandleChange(p, stat);
358 } // end for each record fetched
361 cerr << "Processed " << records << " records\n";
370 t.tv_usec = 250000; // .25 seconds
371 select(0, NULL, NULL, NULL, &t);
374 } // end while pleasestop == 0
377 // When we get to here, the program is exiting.
379 list.del(sampP); // Take the table out of the list
382 conn.setXlaBufferSize(oldsize, NULL, stat);