1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 ***************************************************************************/
16 #include<CacheTableLoader.h>
18 DbRetVal
CacheTableLoader::addToCacheTableFile()
21 fp
= fopen(Conf::config
.getTableConfigFile(),"a");
23 printError(ErrSysInit
, "Invalid path/filename in TABLE_CONFIG_FILE.\nTable will not be"
24 "recovered in case of crash");
27 //TODO::if already table present in the file, it means that the
28 //table is replicated. in this case change mode from
29 //2 to 3 (repl to replcache)
30 fprintf(fp
, "%d:%s\n", 1, tableName
);
35 DbRetVal
CacheTableLoader::removeFromCacheTableFile()
38 char tmpFileName
[MAX_FILE_PATH_LEN
];
39 sprintf(tmpFileName
, "%s.tmp", Conf::config
.getTableConfigFile());
40 tmpfp
= fopen(tmpFileName
,"w");
42 printError(ErrSysInit
, "Invalid path/filename in TABLE_CONFIG_FILE.\n");
45 fp
= fopen(Conf::config
.getTableConfigFile(),"r");
47 printError(ErrSysInit
, "csqltable.conf file does not exist");
50 char tablename
[IDENTIFIER_LENGTH
];
54 fscanf(fp
, "%d:%s\n", &mode
, tablename
);
55 if (strcmp (tablename
, tableName
) == 0) continue;
56 fprintf(tmpfp
, "%d:%s\n", mode
, tablename
);
60 char sysCommand
[MAX_FILE_PATH_LEN
* 2];
61 sprintf(sysCommand
, "mv %s %s", tmpFileName
, Conf::config
.getTableConfigFile());
62 int ret
= system(sysCommand
);
65 printError(ErrSysInit
, "Check csqltable.conf file permission. unable to remove %s from file", tableName
);
71 DbRetVal
CacheTableLoader::load(bool tabDefinition
)
74 DbRetVal rv
= conn
.open(userName
, password
);
75 if (rv
!= OK
) return ErrSysInit
;
76 DatabaseManager
*dbMgr
= (DatabaseManager
*) conn
.getDatabaseManager();
77 if (dbMgr
== NULL
) { printError(ErrSysInit
, "Auth failed\n"); return ErrSysInit
; }
78 conn
.startTransaction();
79 rv
= load(dbMgr
, tabDefinition
);
85 DbRetVal
CacheTableLoader::load(DatabaseManager
*dbMgr
, bool tabDefinition
)
88 sprintf(dsn
, "DSN=%s;", Conf::config
.getDSN());
90 SQLSMALLINT outstrlen
;
96 retValue
= SQLAllocHandle (SQL_HANDLE_ENV
, SQL_NULL_HANDLE
, &henv
);
97 if (retValue
) {printError(ErrSysInit
, "Unable to allocate ODBC handle \n"); return ErrSysInit
; }
98 SQLSetEnvAttr(henv
, SQL_ATTR_ODBC_VERSION
, (void *) SQL_OV_ODBC3
, 0);
99 retValue
= SQLAllocHandle (SQL_HANDLE_DBC
, henv
, &hdbc
);
100 if (retValue
) {printError(ErrSysInit
, "Unable to allocate ODBC handle \n"); return ErrSysInit
; }
101 retValue
= SQLDriverConnect(hdbc
, NULL
, (SQLCHAR
*)dsn
, SQL_NTS
,
102 outstr
, sizeof(outstr
), &outstrlen
,
103 SQL_DRIVER_NOPROMPT
);
104 if (SQL_SUCCEEDED(retValue
)) {
105 printDebug(DM_Gateway
, "Connected to target database using dsn = %s\n", dsn
);
107 fprintf(stderr
, "Failed to connect to target database\n");
111 retValue
=SQLAllocHandle (SQL_HANDLE_STMT
, hdbc
, &hstmt
);
112 if (retValue
) {printError(ErrSysInit
, "Unable to allocate ODBC handle \n"); return ErrSysInit
; }
114 sprintf(stmtBuf
, "SELECT * FROM %s;", tableName
);
115 retValue
= SQLPrepare (hstmt
, (unsigned char *) stmtBuf
, SQL_NTS
);
116 if (retValue
) {printError(ErrSysInit
, "Unable to Prepare ODBC statement \n"); return ErrSysInit
; }
120 retValue
= SQLNumResultCols (hstmt
, &totalFields
);
121 if (retValue
) {printError(ErrSysInit
, "Unable to retrieve ODBC total columns\n"); return ErrSysInit
; }
123 UCHAR colName
[IDENTIFIER_LENGTH
];
131 icol
= 1; colNameMax
= IDENTIFIER_LENGTH
;
132 while (icol
<= totalFields
) {
133 retValue
= SQLDescribeCol(hstmt
, icol
, colName
, colNameMax
,
134 &nameLength
, &colType
, &colLength
,
136 if (retValue
) {printError(ErrSysInit
, "Unable to retrieve ODBC column info\n"); return ErrSysInit
; }
138 printDebug(DM_Gateway
, "Describe Column %s %d %d \n", colName
, colType
, colLength
);
140 tabDef
.addField((char*) colName
, AllDataType::convertFromSQLType(colType
), colLength
);
142 rv
= dbMgr
->createTable(tableName
, tabDef
);
145 printError(ErrSysInit
, "Table creation failed in csql for %s\n", tableName
);
149 char columnname
[124]; char indexname
[124];
150 short type
; short unique
;
152 retValue
=SQLAllocHandle (SQL_HANDLE_STMT
, hdbc
, &hstmtmeta
);
155 printError(ErrSysInit
, "Unable to allocate ODBC handle \n");
159 retValue
= SQLStatistics(hstmtmeta
, NULL
, 0, NULL
, SQL_NTS
,
160 (SQLCHAR
*) tableName
, SQL_NTS
, SQL_INDEX_ALL
, SQL_QUICK
);
161 retValue
= SQLBindCol(hstmtmeta
, 4, SQL_C_SHORT
,
163 retValue
= SQLBindCol(hstmtmeta
, 6, SQL_C_CHAR
,
164 indexname
, 129, NULL
);
165 retValue
= SQLBindCol(hstmtmeta
, 7, SQL_C_SHORT
,
167 retValue
= SQLBindCol(hstmtmeta
, 9, SQL_C_CHAR
,
168 columnname
, 129,NULL
);
169 while ((retValue
= SQLFetch(hstmtmeta
)) == SQL_SUCCESS
)
170 { //if (type != SQL_TABLE_STAT)
172 printDebug(DM_Gateway
, "Column: %-18s Index Name: %-18s unique:%hd type:%hd\n",
173 columnname
, indexname
, unique
, type
);
176 HashIndexInitInfo
*info
= new HashIndexInitInfo();
177 info
->indType
= hashIndex
;
178 info
->bucketSize
= 10007;
179 info
->list
.append(columnname
);
180 strcpy(info
->tableName
, tableName
);
182 sprintf(indname
, "%s_%s", tableName
, indexname
);
183 rv
= dbMgr
->createIndex(indname
, info
);
186 printError(ErrSysInit
, "Index creation failed in csql for %s\n", tableName
);
192 printError(ErrSysInit
,"CSQL does not support this index type\n");
196 }// while meta data fetch for index creation
197 SQLCloseCursor (hstmtmeta
);
198 SQLFreeHandle (SQL_HANDLE_STMT
, hstmtmeta
);
200 Table
*table
= dbMgr
->openTable(tableName
);
202 printError(ErrSysInit
,"unable to open table %d\n", tableName
);
203 dbMgr
->closeTable(table
);
204 if (tabDefinition
) dbMgr
->dropTable(tableName
);
208 table
->setUndoLogging(false);
209 //rv = table->lock(false); //no need to release this lock as it is upgrade from S to X
212 dbMgr
->closeTable(table
);
213 if (tabDefinition
) dbMgr
->dropTable(tableName
);
217 List fNameList
= table
->getFieldNameList();
218 ListIterator fNameIter
= fNameList
.getIterator();
219 FieldInfo
*info
= new FieldInfo();
220 int fcount
=1; void *valBuf
; int fieldsize
=0;
221 Identifier
*elem
= NULL
;
225 while (fNameIter
.hasElement()) {
226 elem
= (Identifier
*) fNameIter
.nextElement();
227 table
->getFieldInfo((const char*)elem
->name
, info
);
228 valBuf
= AllDataType::alloc(info
->type
, info
->length
);
229 table
->bindFld(elem
->name
, valBuf
);
234 fieldsize
= info
->length
;
237 bBuf
= new BindBuffer();
239 bBuf
->type
= typeDate
;
240 fieldsize
= sizeof(DATE_STRUCT
);
241 bBuf
->targetdb
= malloc(fieldsize
);
242 valBuf
= bBuf
->targetdb
;
243 valBufList
.append(bBuf
);
246 bBuf
= new BindBuffer();
248 bBuf
->type
= typeTime
;
249 fieldsize
= sizeof(TIME_STRUCT
);
250 bBuf
->targetdb
= malloc(fieldsize
);
251 valBuf
= bBuf
->targetdb
;
252 valBufList
.append(bBuf
);
255 bBuf
= new BindBuffer();
257 bBuf
->type
= typeTimeStamp
;
258 fieldsize
= sizeof(TIMESTAMP_STRUCT
);
259 bBuf
->targetdb
= malloc(fieldsize
);
260 valBuf
= bBuf
->targetdb
;
261 valBufList
.append(bBuf
);
264 retValue
= SQLBindCol (hstmt
, fcount
++, AllDataType::convertToSQLType(info
->type
),
265 valBuf
, fieldsize
, NULL
);
266 if (retValue
) {printError(ErrSysInit
, "Unable to bind columns in ODBC\n"); return ErrSysInit
; }
269 retValue
= SQLExecute (hstmt
);
270 if (retValue
) {printError(ErrSysInit
, "Unable to execute ODBC statement\n"); return ErrSysInit
; }
273 retValue
= SQLFetch (hstmt
);
275 ListIterator bindIter
= valBufList
.getIterator();
276 while (bindIter
.hasElement()) {
277 bBuf
= (BindBuffer
*) bindIter
.nextElement();
278 switch (bBuf
->type
) {
280 Date
*dtCSQL
= (Date
*) bBuf
->csql
;
281 DATE_STRUCT
*dtTarget
= (DATE_STRUCT
*) bBuf
->targetdb
;
282 dtCSQL
->set(dtTarget
->year
,dtTarget
->month
,dtTarget
->day
);
286 Time
*dtCSQL
= (Time
*) bBuf
->csql
;
287 TIME_STRUCT
*dtTarget
= (TIME_STRUCT
*) bBuf
->targetdb
;
288 dtCSQL
->set(dtTarget
->hour
,dtTarget
->minute
,dtTarget
->second
);
291 case typeTimeStamp
: {
292 TimeStamp
*dtCSQL
= (TimeStamp
*) bBuf
->csql
;
293 TIMESTAMP_STRUCT
*dtTarget
= (TIMESTAMP_STRUCT
*) bBuf
->targetdb
;
294 dtCSQL
->setDate(dtTarget
->year
,dtTarget
->month
,dtTarget
->day
);
295 dtCSQL
->setTime(dtTarget
->hour
,dtTarget
->minute
,dtTarget
->second
, dtTarget
->fraction
);
300 table
->insertTuple();
302 //TODO::leak:: valBufList and its targetdb buffer
304 dbMgr
->closeTable(table
);
305 SQLCloseCursor (hstmt
);
306 SQLFreeHandle (SQL_HANDLE_STMT
, hstmt
);
307 SQLDisconnect (hdbc
);
308 SQLFreeHandle (SQL_HANDLE_DBC
, hdbc
);
309 SQLFreeHandle (SQL_HANDLE_ENV
, henv
);
313 DbRetVal
CacheTableLoader::reload()
315 DbRetVal rv
= unload(false);
316 if (rv
!= OK
) return rv
;
321 DbRetVal
CacheTableLoader::unload(bool tabDefinition
)
324 DbRetVal rv
= conn
.open(userName
, password
);
325 if (rv
!= OK
) return ErrSysInit
;
326 DatabaseManager
*dbMgr
= (DatabaseManager
*) conn
.getDatabaseManager();
327 if (dbMgr
== NULL
) { printError(ErrSysInit
, "Auth failed\n"); return ErrSysInit
; }
330 Table
*table
= dbMgr
->openTable(tableName
);
331 if (table
== NULL
) { conn
.close(); return ErrBadCall
; }
332 rv
= conn
.startTransaction();
333 if (rv
!= OK
) { dbMgr
->closeTable(table
); conn
.close(); return ErrBadCall
; }
336 dbMgr
->closeTable(table
);
340 rv
= dbMgr
->dropTable(tableName
);
347 DbRetVal
CacheTableLoader::refresh()
352 DbRetVal
CacheTableLoader::recoverAllCachedTables()
356 DbRetVal rv
= conn
.open(userName
, password
);
357 //Note: if connection is not open, configuration veriables may be incorrect
359 fp
= fopen(Conf::config
.getTableConfigFile(),"r");
361 printError(ErrSysInit
, "cachetable.conf file does not exist");
365 //TODO::take exclusive lock on database
366 char tablename
[IDENTIFIER_LENGTH
];
371 fscanf(fp
, "%d:%s\n", &mode
, tablename
);
372 if (mode
==2 ) //just replicated table and not cached
374 printDebug(DM_Gateway
, "Recovering Table from target db: %s\n", tablename
);
376 printf("Recovering table %s\n", tablename
);
378 if (rv
!= OK
) return rv
;