xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1 // Copyright 1997-2021 The OpenLDAP Foundation, All Rights Reserved.
2 //  COPYING RESTRICTIONS APPLY, see COPYRIGHT file
3 
4 // (c) Copyright 1999-2001 TimesTen Performance Software. All rights reserved.
5 
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
9 
10 #include <stdlib.h>
11 
12 #include <TTConnectionPool.h>
13 #include <TTConnection.h>
14 #include <TTCmd.h>
15 #include <TTXla.h>
16 
17 #include <signal.h>
18 
19 TTConnectionPool pool;
20 TTXlaConnection  conn;
21 TTConnection     conn2;
22 TTCmd            assignDn_ru;
23 TTCmd            getNullDNs;
24 
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 //----------------------------------------------------------------------
32 
33 class LDAPEntriesHandler: public TTXlaTableHandler {
34 private:
35   // Definition of the columns in the table
36   int Id;
37   int Dn;
38   int Oc_map_id;
39   int Parent;
40   int Keyval;
41   int Dn_ru;
42 
43 protected:
44 
45 public:
46   LDAPEntriesHandler(TTXlaConnection& conn, const char* ownerP, const char* nameP);
47   ~LDAPEntriesHandler();
48 
49   virtual void HandleDelete(ttXlaUpdateDesc_t*);
50   virtual void HandleInsert(ttXlaUpdateDesc_t*);
51   virtual void HandleUpdate(ttXlaUpdateDesc_t*);
52 
53   static void ReverseAndUpper(char* dnP, int id, bool commit=true);
54 
55 };
56 
LDAPEntriesHandler(TTXlaConnection & conn,const char * ownerP,const char * nameP)57 LDAPEntriesHandler::LDAPEntriesHandler(TTXlaConnection& conn,
58 				       const char* ownerP, const char* nameP) :
59   TTXlaTableHandler(conn, ownerP, nameP)
60 {
61   Id = Dn = Oc_map_id = Parent = Keyval = Dn_ru = -1;
62 
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.
65 
66   Id = tbl.getColNumber("ID");
67   if (Id < 0) {
68     cerr << "target table has no 'ID' column" << endl;
69     exit(1);
70   }
71   Dn = tbl.getColNumber("DN");
72   if (Dn < 0) {
73     cerr << "target table has no 'DN' column" << endl;
74     exit(1);
75   }
76   Oc_map_id = tbl.getColNumber("OC_MAP_ID");
77   if (Oc_map_id < 0) {
78     cerr << "target table has no 'OC_MAP_ID' column" << endl;
79     exit(1);
80   }
81   Parent = tbl.getColNumber("PARENT");
82   if (Parent < 0) {
83     cerr << "target table has no 'PARENT' column" << endl;
84     exit(1);
85   }
86   Keyval = tbl.getColNumber("KEYVAL");
87   if (Keyval < 0) {
88     cerr << "target table has no 'KEYVAL' column" << endl;
89     exit(1);
90   }
91   Dn_ru = tbl.getColNumber("DN_RU");
92   if (Dn_ru < 0) {
93     cerr << "target table has no 'DN_RU' column" << endl;
94     exit(1);
95   }
96 
97 }
98 
~LDAPEntriesHandler()99 LDAPEntriesHandler::~LDAPEntriesHandler()
100 {
101 
102 }
103 
ReverseAndUpper(char * dnP,int id,bool commit)104 void LDAPEntriesHandler::ReverseAndUpper(char* dnP, int id, bool commit)
105 {
106   TTStatus stat;
107   char dn_rn[512];
108   int i;
109   int j;
110 
111   // Reverse and upper case the given DN
112 
113   for ((j=0, i = strlen(dnP)-1); i > -1; (j++, i--)) {
114     dn_rn[j] = toupper(*(dnP+i));
115   }
116   dn_rn[j] = '\0';
117 
118 
119   // Update the database
120 
121   try {
122     assignDn_ru.setParam(1, (char*) &dn_rn[0]);
123     assignDn_ru.setParam(2, id);
124     assignDn_ru.Execute(stat);
125   }
126   catch (TTStatus stat) {
127     cerr << "Error updating id " << id << " ('" << dnP << "' to '"
128 	 << dn_rn << "'): " << stat;
129     exit(1);
130   }
131 
132   // Commit the transaction
133 
134   if (commit) {
135     try {
136       conn2.Commit(stat);
137     }
138     catch (TTStatus stat) {
139       cerr << "Error committing update: " << stat;
140       exit(1);
141     }
142   }
143 
144 }
145 
146 
147 
HandleInsert(ttXlaUpdateDesc_t * p)148 void LDAPEntriesHandler::HandleInsert(ttXlaUpdateDesc_t* p)
149 {
150   char* dnP;
151   int   id;
152 
153   row.Get(Dn, &dnP);
154   cerr << "DN '" << dnP << "': Inserted ";
155   row.Get(Id, &id);
156 
157   ReverseAndUpper(dnP, id);
158 
159 }
160 
HandleUpdate(ttXlaUpdateDesc_t * p)161 void LDAPEntriesHandler::HandleUpdate(ttXlaUpdateDesc_t* p)
162 {
163   char* newDnP;
164   char* oldDnP;
165   char  oDn[512];
166   int   id;
167 
168   // row is 'old'; row2 is 'new'
169   row.Get(Dn, &oldDnP);
170   strcpy(oDn, oldDnP);
171   row.Get(Id, &id);
172   row2.Get(Dn, &newDnP);
173 
174   cerr << "old DN '" << oDn << "' / new DN '" << newDnP << "' : Updated ";
175 
176   if (strcmp(oDn, newDnP) != 0) {
177     // The DN field changed, update it
178     cerr << "(new DN: '" << newDnP << "')";
179     ReverseAndUpper(newDnP, id);
180   }
181   else {
182     // The DN field did NOT change, leave it alone
183   }
184 
185   cerr << endl;
186 
187 }
188 
HandleDelete(ttXlaUpdateDesc_t * p)189 void LDAPEntriesHandler::HandleDelete(ttXlaUpdateDesc_t* p)
190 {
191   char* dnP;
192 
193   row.Get(Dn, &dnP);
194   cerr << "DN '" << dnP << "': Deleted ";
195 }
196 
197 
198 
199 
200 //----------------------------------------------------------------------
201 
202 int pleaseStop = 0;
203 
204 extern "C" {
205   void
onintr(int sig)206   onintr(int sig)
207   {
208     pleaseStop = 1;
209     cerr << "Stopping...\n";
210   }
211 };
212 
213 //----------------------------------------------------------------------
214 
215 int
main(int argc,char * argv[])216 main(int argc, char* argv[])
217 {
218 
219   char* ownerP;
220 
221   TTXlaTableList list(&conn);	// List of tables to monitor
222 
223   // Handlers, one for each table we want to monitor
224 
225   LDAPEntriesHandler* sampP = NULL;
226 
227   // Misc stuff
228 
229   TTStatus stat;
230 
231   ttXlaUpdateDesc_t ** arry;
232 
233   int records;
234 
235   SQLUBIGINT  oldsize;
236   int j;
237 
238   if (argc < 2) {
239     cerr << "syntax: " << argv[0] << " <username>" << endl;
240     exit(3);
241   }
242 
243   ownerP = argv[1];
244 
245   signal(SIGINT, onintr);    /* signal for CTRL-C */
246 #ifdef _WIN32
247   signal(SIGBREAK, onintr);  /* signal for CTRL-BREAK */
248 #endif
249 
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.
253 
254   try {
255     cerr << "Connecting..." << endl;
256 
257     conn2.Connect("DSN=ldap_tt", stat);
258   }
259   catch (TTStatus stat) {
260     cerr << "Error connecting to TimesTen: " << stat;
261     exit(1);
262   }
263 
264   try {
265     assignDn_ru.Prepare(&conn2,
266 			"update ldap_entries set dn_ru=? where id=?",
267 			"", stat);
268     getNullDNs.Prepare(&conn2,
269 		       "select dn, id from ldap_entries "
270 			"where dn_ru is null "
271 			"for update",
272 		       "", stat);
273     conn2.Commit(stat);
274   }
275   catch (TTStatus stat) {
276     cerr << "Error preparing update: " << stat;
277     exit(1);
278   }
279 
280   // If there are any entries with a NULL reversed/upper cased DN,
281   // fix them now.
282 
283   try {
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;
289       char* dnP;
290       int   id;
291       getNullDNs.getColumn(1, &dnP);
292       getNullDNs.getColumn(2, &id);
293       // cerr << "Id " << id << ", Dn '" << dnP << "'" << endl;
294       LDAPEntriesHandler::ReverseAndUpper(dnP, id, false);
295       if (k % 1000 == 0)
296         cerr << ".";
297     }
298     getNullDNs.Close(stat);
299     conn2.Commit(stat);
300   }
301   catch (TTStatus stat) {
302     cerr << "Error updating NULL rows: " << stat;
303     exit(1);
304   }
305 
306 
307   // Go ahead and start up the change monitoring application
308 
309   cerr << "Starting change monitoring..." << endl;
310   try {
311     conn.Connect("DSN=ldap_tt", stat);
312   }
313   catch (TTStatus stat) {
314     cerr << "Error connecting to TimesTen: " << stat;
315     exit(1);
316   }
317 
318   /* set and configure size of buffer */
319   conn.setXlaBufferSize((SQLUBIGINT) 1000000, &oldsize, stat);
320   if (stat.rc) {
321     cerr << "Error setting buffer size " << stat << endl;
322     exit(1);
323   }
324 
325   // Make a handler to process changes to the MYDATA table and
326   // add the handler to the list of all handlers
327 
328   sampP = new LDAPEntriesHandler(conn, ownerP, "ldap_entries");
329   if (!sampP) {
330     cerr << "Could not create LDAPEntriesHandler" << endl;
331     exit(3);
332   }
333   list.add(sampP);
334 
335   // Enable transaction logging for the table we're interested in
336 
337   sampP->EnableTracking(stat);
338 
339   // Get updates.  Dispatch them to the appropriate handler.
340   // This loop will handle updates to all the tables.
341 
342   while (pleaseStop == 0) {
343     conn.fetchUpdates(&arry, 1000, &records, stat);
344     if (stat.rc) {
345       cerr << "Error fetching updates" << stat << endl;
346       exit(1);
347     }
348 
349     // Interpret the updates
350 
351     for(j=0;j < records;j++){
352       ttXlaUpdateDesc_t *p;
353 
354       p = arry[j];
355 
356       list.HandleChange(p, stat);
357 
358     } // end for each record fetched
359 
360     if (records) {
361       cerr << "Processed " << records << " records\n";
362     }
363 
364     if (records == 0) {
365 #ifdef _WIN32
366       Sleep(250);
367 #else
368       struct timeval t;
369       t.tv_sec = 0;
370       t.tv_usec = 250000; // .25 seconds
371       select(0, NULL, NULL, NULL, &t);
372 #endif
373     }
374   } // end while pleasestop == 0
375 
376 
377   // When we get to here, the program is exiting.
378 
379   list.del(sampP);		// Take the table out of the list
380   delete sampP;
381 
382   conn.setXlaBufferSize(oldsize, NULL, stat);
383 
384   return 0;
385 
386 }
387 
388