]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp
Happy New Year
[openldap] / servers / slapd / back-sql / rdbms_depend / timesten / dnreverse / dnreverse.cpp
1 // Copyright 1997-2015 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 intregal 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
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
99 LDAPEntriesHandler::~LDAPEntriesHandler()
100 {
101
102 }
103
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
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
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
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
206   onintr(int sig)
207   {
208     pleaseStop = 1;
209     cerr << "Stopping...\n";
210   }
211 };
212
213 //----------------------------------------------------------------------
214
215 int 
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