#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;
class LDAPEntriesHandler: public TTXlaTableHandler {
private:
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;
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;
for ((j=0, i = strlen(dnP)-1); i > -1; (j++, i--)) {
dn_rn[j] = toupper(*(dnP+i));
}
dn_rn[j] = '\0';
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);
}
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.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) {
cerr << "(new DN: '" << newDnP << "')";
ReverseAndUpper(newDnP, id);
}
else {
}
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);
LDAPEntriesHandler* sampP = NULL;
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);
#ifdef _WIN32
signal(SIGBREAK, onintr);
#endif
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);
}
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);
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);
}
cerr << "Starting change monitoring..." << endl;
try {
conn.Connect("DSN=ldap_tt", stat);
}
catch (TTStatus stat) {
cerr << "Error connecting to TimesTen: " << stat;
exit(1);
}
conn.setXlaBufferSize((SQLUBIGINT) 1000000, &oldsize, stat);
if (stat.rc) {
cerr << "Error setting buffer size " << stat << endl;
exit(1);
}
sampP = new LDAPEntriesHandler(conn, ownerP, "ldap_entries");
if (!sampP) {
cerr << "Could not create LDAPEntriesHandler" << endl;
exit(3);
}
list.add(sampP);
sampP->EnableTracking(stat);
while (pleaseStop == 0) {
conn.fetchUpdates(&arry, 1000, &records, stat);
if (stat.rc) {
cerr << "Error fetching updates" << stat << endl;
exit(1);
}
for(j=0;j < records;j++){
ttXlaUpdateDesc_t *p;
p = arry[j];
list.HandleChange(p, stat);
}
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; select(0, NULL, NULL, NULL, &t);
#endif
}
}
list.del(sampP); delete sampP;
conn.setXlaBufferSize(oldsize, NULL, stat);
return 0;
}