Back to index

openldap  2.4.31
dnreverse.cpp
Go to the documentation of this file.
00001 // Copyright 1997-2012 The OpenLDAP Foundation, All Rights Reserved.
00002 //  COPYING RESTRICTIONS APPLY, see COPYRIGHT file
00003 
00004 // (c) Copyright 1999-2001 TimesTen Performance Software. All rights reserved.
00005 
00009 
00010 #include <stdlib.h>
00011 
00012 #include <TTConnectionPool.h>
00013 #include <TTConnection.h>
00014 #include <TTCmd.h>
00015 #include <TTXla.h>
00016 
00017 #include <signal.h>
00018 
00019 TTConnectionPool pool;
00020 TTXlaConnection  conn;
00021 TTConnection     conn2;
00022 TTCmd            assignDn_ru;
00023 TTCmd            getNullDNs;
00024 
00025 //----------------------------------------------------------------------
00026 // This class contains all the logic to be implemented whenever
00027 // the SCOTT.MYDATA table is changed.  This is the table that is
00028 // created by "sample.cpp", one of the other TTClasses demos.
00029 // That application should be executed before this one in order to 
00030 // create and populate the table.
00031 //----------------------------------------------------------------------
00032 
00033 class LDAPEntriesHandler: public TTXlaTableHandler {
00034 private:
00035   // Definition of the columns in the table
00036   int Id;
00037   int Dn;
00038   int Oc_map_id;
00039   int Parent;
00040   int Keyval;
00041   int Dn_ru;
00042 
00043 protected:
00044 
00045 public:
00046   LDAPEntriesHandler(TTXlaConnection& conn, const char* ownerP, const char* nameP);
00047   ~LDAPEntriesHandler();
00048 
00049   virtual void HandleDelete(ttXlaUpdateDesc_t*);
00050   virtual void HandleInsert(ttXlaUpdateDesc_t*);
00051   virtual void HandleUpdate(ttXlaUpdateDesc_t*);
00052 
00053   static void ReverseAndUpper(char* dnP, int id, bool commit=true);
00054 
00055 };
00056 
00057 LDAPEntriesHandler::LDAPEntriesHandler(TTXlaConnection& conn,
00058                                    const char* ownerP, const char* nameP) :
00059   TTXlaTableHandler(conn, ownerP, nameP)
00060 {
00061   Id = Dn = Oc_map_id = Parent = Keyval = Dn_ru = -1;
00062 
00063   // We are looking for several particular named columns.  We need to get
00064   // the ordinal position of the columns by name for later use.
00065 
00066   Id = tbl.getColNumber("ID");
00067   if (Id < 0) {
00068     cerr << "target table has no 'ID' column" << endl;
00069     exit(1);
00070   }
00071   Dn = tbl.getColNumber("DN");
00072   if (Dn < 0) {
00073     cerr << "target table has no 'DN' column" << endl;
00074     exit(1);
00075   }
00076   Oc_map_id = tbl.getColNumber("OC_MAP_ID");
00077   if (Oc_map_id < 0) {
00078     cerr << "target table has no 'OC_MAP_ID' column" << endl;
00079     exit(1);
00080   }
00081   Parent = tbl.getColNumber("PARENT");
00082   if (Parent < 0) {
00083     cerr << "target table has no 'PARENT' column" << endl;
00084     exit(1);
00085   }
00086   Keyval = tbl.getColNumber("KEYVAL");
00087   if (Keyval < 0) {
00088     cerr << "target table has no 'KEYVAL' column" << endl;
00089     exit(1);
00090   }
00091   Dn_ru = tbl.getColNumber("DN_RU");
00092   if (Dn_ru < 0) {
00093     cerr << "target table has no 'DN_RU' column" << endl;
00094     exit(1);
00095   }
00096 
00097 }
00098 
00099 LDAPEntriesHandler::~LDAPEntriesHandler()
00100 {
00101 
00102 }
00103 
00104 void LDAPEntriesHandler::ReverseAndUpper(char* dnP, int id, bool commit)
00105 {
00106   TTStatus stat;
00107   char dn_rn[512];
00108   int i;
00109   int j;
00110 
00111   // Reverse and upper case the given DN
00112 
00113   for ((j=0, i = strlen(dnP)-1); i > -1; (j++, i--)) {
00114     dn_rn[j] = toupper(*(dnP+i));
00115   }
00116   dn_rn[j] = '\0';
00117 
00118 
00119   // Update the database
00120 
00121   try {
00122     assignDn_ru.setParam(1, (char*) &dn_rn[0]);
00123     assignDn_ru.setParam(2, id);
00124     assignDn_ru.Execute(stat);
00125   }
00126   catch (TTStatus stat) {
00127     cerr << "Error updating id " << id << " ('" << dnP << "' to '" 
00128         << dn_rn << "'): " << stat;
00129     exit(1);
00130   }
00131 
00132   // Commit the transaction
00133   
00134   if (commit) {
00135     try {
00136       conn2.Commit(stat);
00137     }
00138     catch (TTStatus stat) {
00139       cerr << "Error committing update: " << stat;
00140       exit(1);
00141     }
00142   }
00143 
00144 }
00145 
00146 
00147 
00148 void LDAPEntriesHandler::HandleInsert(ttXlaUpdateDesc_t* p)
00149 {
00150   char* dnP; 
00151   int   id;
00152 
00153   row.Get(Dn, &dnP);
00154   cerr << "DN '" << dnP << "': Inserted ";
00155   row.Get(Id, &id);
00156 
00157   ReverseAndUpper(dnP, id);
00158 
00159 }
00160 
00161 void LDAPEntriesHandler::HandleUpdate(ttXlaUpdateDesc_t* p)
00162 {    
00163   char* newDnP; 
00164   char* oldDnP;
00165   char  oDn[512];
00166   int   id;
00167 
00168   // row is 'old'; row2 is 'new'
00169   row.Get(Dn, &oldDnP);
00170   strcpy(oDn, oldDnP);
00171   row.Get(Id, &id);
00172   row2.Get(Dn, &newDnP);
00173   
00174   cerr << "old DN '" << oDn << "' / new DN '" << newDnP << "' : Updated ";
00175 
00176   if (strcmp(oDn, newDnP) != 0) {  
00177     // The DN field changed, update it
00178     cerr << "(new DN: '" << newDnP << "')";
00179     ReverseAndUpper(newDnP, id);
00180   }
00181   else {
00182     // The DN field did NOT change, leave it alone
00183   }
00184 
00185   cerr << endl;
00186 
00187 }
00188 
00189 void LDAPEntriesHandler::HandleDelete(ttXlaUpdateDesc_t* p)
00190 {    
00191   char* dnP; 
00192 
00193   row.Get(Dn, &dnP);
00194   cerr << "DN '" << dnP << "': Deleted ";
00195 }
00196 
00197 
00198 
00199 
00200 //----------------------------------------------------------------------
00201 
00202 int pleaseStop = 0;
00203 
00204 extern "C" {
00205   void
00206   onintr(int sig)
00207   {
00208     pleaseStop = 1;
00209     cerr << "Stopping...\n";
00210   }
00211 };
00212 
00213 //----------------------------------------------------------------------
00214 
00215 int 
00216 main(int argc, char* argv[])
00217 {
00218 
00219   char* ownerP;
00220 
00221   TTXlaTableList list(&conn);      // List of tables to monitor
00222 
00223   // Handlers, one for each table we want to monitor
00224 
00225   LDAPEntriesHandler* sampP = NULL;
00226 
00227   // Misc stuff
00228 
00229   TTStatus stat;
00230 
00231   ttXlaUpdateDesc_t ** arry;
00232 
00233   int records;
00234 
00235   SQLUBIGINT  oldsize;
00236   int j;
00237 
00238   if (argc < 2) {
00239     cerr << "syntax: " << argv[0] << " <username>" << endl;
00240     exit(3);
00241   }
00242 
00243   ownerP = argv[1];
00244 
00245   signal(SIGINT, onintr);    /* signal for CTRL-C */
00246 #ifdef _WIN32
00247   signal(SIGBREAK, onintr);  /* signal for CTRL-BREAK */
00248 #endif
00249 
00250   // Before we do anything related to XLA, first we connect
00251   // to the database.  This is the connection we will use
00252   // to perform non-XLA operations on the tables.
00253 
00254   try {
00255     cerr << "Connecting..." << endl;
00256 
00257     conn2.Connect("DSN=ldap_tt", stat);
00258   }
00259   catch (TTStatus stat) {
00260     cerr << "Error connecting to TimesTen: " << stat;
00261     exit(1);
00262   }
00263 
00264   try {
00265     assignDn_ru.Prepare(&conn2,
00266                      "update ldap_entries set dn_ru=? where id=?", 
00267                      "", stat);
00268     getNullDNs.Prepare(&conn2,
00269                      "select dn, id from ldap_entries "
00270                      "where dn_ru is null "
00271                      "for update", 
00272                      "", stat);
00273     conn2.Commit(stat);
00274   }
00275   catch (TTStatus stat) {
00276     cerr << "Error preparing update: " << stat;
00277     exit(1);
00278   }
00279 
00280   // If there are any entries with a NULL reversed/upper cased DN, 
00281   // fix them now.
00282 
00283   try {
00284     cerr << "Fixing NULL reversed DNs" << endl;
00285     getNullDNs.Execute(stat);
00286     for (int k = 0;; k++) {
00287       getNullDNs.FetchNext(stat);
00288       if (stat.rc == SQL_NO_DATA_FOUND) break;
00289       char* dnP;
00290       int   id;
00291       getNullDNs.getColumn(1, &dnP);
00292       getNullDNs.getColumn(2, &id);
00293       // cerr << "Id " << id << ", Dn '" << dnP << "'" << endl;
00294       LDAPEntriesHandler::ReverseAndUpper(dnP, id, false);
00295       if (k % 1000 == 0) 
00296         cerr << ".";
00297     }
00298     getNullDNs.Close(stat);
00299     conn2.Commit(stat);
00300   }
00301   catch (TTStatus stat) {
00302     cerr << "Error updating NULL rows: " << stat;
00303     exit(1);
00304   }
00305 
00306 
00307   // Go ahead and start up the change monitoring application
00308 
00309   cerr << "Starting change monitoring..." << endl;
00310   try {
00311     conn.Connect("DSN=ldap_tt", stat);
00312   }
00313   catch (TTStatus stat) {
00314     cerr << "Error connecting to TimesTen: " << stat;
00315     exit(1);
00316   }
00317 
00318   /* set and configure size of buffer */
00319   conn.setXlaBufferSize((SQLUBIGINT) 1000000, &oldsize, stat);
00320   if (stat.rc) {
00321     cerr << "Error setting buffer size " << stat << endl;
00322     exit(1);
00323   }
00324 
00325   // Make a handler to process changes to the MYDATA table and
00326   // add the handler to the list of all handlers
00327 
00328   sampP = new LDAPEntriesHandler(conn, ownerP, "ldap_entries");
00329   if (!sampP) {
00330     cerr << "Could not create LDAPEntriesHandler" << endl;
00331     exit(3);
00332   }
00333   list.add(sampP);
00334 
00335   // Enable transaction logging for the table we're interested in 
00336 
00337   sampP->EnableTracking(stat);
00338 
00339   // Get updates.  Dispatch them to the appropriate handler.
00340   // This loop will handle updates to all the tables.
00341 
00342   while (pleaseStop == 0) {
00343     conn.fetchUpdates(&arry, 1000, &records, stat);
00344     if (stat.rc) {
00345       cerr << "Error fetching updates" << stat << endl;
00346       exit(1);
00347     }
00348 
00349     // Interpret the updates
00350 
00351     for(j=0;j < records;j++){
00352       ttXlaUpdateDesc_t *p;
00353 
00354       p = arry[j];
00355 
00356       list.HandleChange(p, stat);
00357 
00358     } // end for each record fetched
00359     
00360     if (records) {
00361       cerr << "Processed " << records << " records\n";
00362     }
00363 
00364     if (records == 0) {
00365 #ifdef _WIN32
00366       Sleep(250);
00367 #else
00368       struct timeval t;
00369       t.tv_sec = 0;
00370       t.tv_usec = 250000; // .25 seconds
00371       select(0, NULL, NULL, NULL, &t);
00372 #endif
00373     }
00374   } // end while pleasestop == 0
00375   
00376 
00377   // When we get to here, the program is exiting.
00378 
00379   list.del(sampP);          // Take the table out of the list 
00380   delete sampP;
00381 
00382   conn.setXlaBufferSize(oldsize, NULL, stat);
00383 
00384   return 0;
00385 
00386 }
00387