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 ***************************************************************************/
18 #include<SessionImpl.h>
22 #include<Transaction.h>
24 #include<CacheTableLoader.h>
25 char* version
= "csql-linux-i686-2.0GA";
29 bool recoverFlag
=false;
31 SessionImpl
*session
= NULL
;
32 static void sigTermHandler(int sig
)
34 printf("Received signal %d\nStopping the server\n", sig
);
38 bool checkDead(pid_t pid
)
40 int ret
= os::kill(pid
, 0);
41 if (ret
== -1) return true; else return false;
44 DbRetVal
releaseAllResources(Database
*sysdb
, ThreadInfo
*info
)
46 printf("Releasing all the resources for process %d %lu\n", info
->pid_
, info
->thrid_
);
47 //recover for all the mutexes in has_
48 for (int i
=0; i
< MAX_MUTEX_PER_THREAD
; i
++)
50 if (info
->has_
[i
] != NULL
)
52 printf("Dead Procs: %d %lu holding mutex %x %s \n", info
->pid_
, info
->thrid_
, info
->has_
[i
], info
->has_
[i
]->name
);
53 logFine(Conf::logger
, "Dead Procs: %d %lu holding mutex %x %s \n", info
->pid_
, info
->thrid_
, info
->has_
[i
], info
->has_
[i
]->name
);
54 //TODO::recovery of mutexes
55 sysdb
->recoverMutex(info
->has_
[i
]);
60 TransactionManager
*tm
= new TransactionManager();
61 LockManager
*lm
= new LockManager(sysdb
);
62 for (int i
= 0 ;i
< MAX_THREADS_PER_PROCESS
; i
++)
64 if (info
->thrTrans_
[i
].trans_
!= NULL
&& info
->thrTrans_
[i
].trans_
->status_
== TransRunning
)
66 printf("Rollback Transaction %x\n", info
->thrTrans_
[i
].trans_
);
67 tm
->rollback(lm
, info
->thrTrans_
[i
].trans_
);
68 info
->thrTrans_
[i
].trans_
->status_
= TransNotUsed
;
77 DbRetVal
cleanupDeadProcs(Database
*sysdb
)
79 DbRetVal rv
= sysdb
->getProcessTableMutex(false);
82 printError(rv
,"Unable to get process table mutex");
87 pthread_t thrid
= os::getthrid();
90 ThreadInfo
* pInfo
= sysdb
->getThreadInfo(0);
92 ThreadInfo
* freeSlot
= NULL
;
93 for (; i
< Conf::config
.getMaxProcs(); i
++)
95 //check whether it is alive
96 if (pInfo
->pid_
!=0 && checkDead(pInfo
->pid_
)) releaseAllResources(sysdb
, pInfo
);
99 sysdb
->releaseProcessTableMutex(false);
104 DbRetVal
logActiveProcs(Database
*sysdb
)
106 DbRetVal rv
= sysdb
->getProcessTableMutex(false);
109 printError(rv
,"Unable to get process table mutex");
112 ThreadInfo
* pInfo
= sysdb
->getThreadInfo(0);
114 ThreadInfo
* freeSlot
= NULL
;
115 for (; i
< Conf::config
.getMaxProcs(); i
++)
117 if (pInfo
->pid_
!=0 ) {
118 logFine(Conf::logger
, "Registered Procs: %d %lu\n", pInfo
->pid_
, pInfo
->thrid_
);
119 printf("Client process with pid %d is still registered\n", pInfo
->pid_
);
124 sysdb
->releaseProcessTableMutex(false);
125 if (count
) return ErrSysInternal
; else return OK
;
127 void startCacheServer()
129 printf("Starting Cache Recv Server\n");
131 sprintf(execName
, "%s/bin/csqlcacheserver", os::getenv("CSQL_INSTALL_ROOT"));
132 printf("filename is %s\n", execName
);
133 cachepid
= os::createProcess(execName
, "csqlcacheserver");
135 printf("Cache Recv Server Started pid=%d\n", cachepid
);
139 void startServiceClient()
141 printf("Starting Csql Network Daemon\n");
143 sprintf(execName
, "%s/bin/csqlsqlserver", os::getenv("CSQL_INSTALL_ROOT"));
144 printf("filename is %s\n", execName
);
145 sqlserverpid
= os::createProcess(execName
, "csqlsqlserver");
146 if (sqlserverpid
!= -1)
147 printf("Csql Network Daemon Started pid=%d\n", sqlserverpid
);
153 printf("Usage: csqlserver [-c] [-v]\n");
154 printf(" v -> print the version.\n");
155 printf(" c -> recover all cached tables from the target database.\n");
156 printf("Description: Start the csql server and initialize the database.\n");
159 int main(int argc
, char **argv
)
162 while ((c
= getopt(argc
, argv
, "cv?")) != EOF
)
166 case '?' : { opt
= 10; break; } //print help
167 case 'c' : { opt
= 1; break; } //recover all the tables from cache
168 case 'v' : { opt
= 2; break; } //print version
178 printf("%s\n",version
);
181 session
= new SessionImpl();
182 DbRetVal rv
= session
->readConfigFile();
185 printf("Unable to read the configuration file \n");
188 os::signal(SIGINT
, sigTermHandler
);
189 os::signal(SIGTERM
, sigTermHandler
);
190 rv
= Conf::logger
.startLogger(Conf::config
.getLogFile(), true);
193 printf("Unable to start the logger\n");
197 logFine(Conf::logger
, "Server Started");
198 int ret
= session
->initSystemDatabase();
201 //printf(" System Database Initialization failed\n");
202 printf("Attaching to exising database\n");
205 session
= new SessionImpl();
206 ret
= session
->open(DBAUSER
, DBAPASS
);
208 printf("Unable to attach to existing database\n");
212 printf("System Database initialized\n");
216 struct timeval timeout
, tval
;
219 Database
* sysdb
= session
->getSystemDatabase();
221 if(isInit
&& Conf::config
.useDurability())
223 char dbChkptFileName
[1024];
224 char dbRedoFileName
[1024];
226 sprintf(dbChkptFileName
, "%s/csql.db.chkpt", Conf::config
.getDbFile());
227 if (FILE *file
= fopen(dbChkptFileName
, "r"))
230 sprintf(cmd
, "csql -X -s %s",dbChkptFileName
);
231 int ret
= system(cmd
);
233 printf("Tables cannot be recovered. chkpt file corrupted\n");
236 sprintf(dbRedoFileName
, "%s/csql.db.cur", Conf::config
.getDbFile());
237 if (FILE *file
= fopen(dbRedoFileName
, "r"))
240 int ret
= system("redo -a");
242 printf("Recovery failed. Redo log file corrupted\n");
243 Conf::logger
.stopLogger();
244 session
->destroySystemDatabase();
248 //TODO::generate checkpoint file
249 sprintf(cmd
, "csqldump -X > %s",dbChkptFileName
);
252 printf("Unable to create checkpoint file\n");
253 Conf::logger
.stopLogger();
254 session
->destroySystemDatabase();
258 ret
= unlink(dbRedoFileName
);
260 printf("Unable to delete redo log file. Delete and restart the server\n");
261 Conf::logger
.stopLogger();
262 session
->destroySystemDatabase();
269 if (opt
== 1 && isInit
&& ! Conf::config
.useDurability()) {
270 if (Conf::config
.useCache()) {
271 printf("Database server recovering cached tables...\n");
272 int ret
= system("cachetable -U root -P manager -R");
274 printf("Cached Tables recovery failed %d\n", ret
);
275 Conf::logger
.stopLogger();
276 session
->destroySystemDatabase();
280 printf("Cached Tables recovered\n");
282 printf("Cache mode is not set in csql.conf. Cannot recover\n");
283 Conf::logger
.stopLogger();
284 session
->destroySystemDatabase();
290 if (isInit
) UID
.create();
291 //TODO:: kill all the child servers and restart if !isInit
293 bool isCacheReq
= false, isSQLReq
= false;
294 if(Conf::config
.useCsqlSqlServer()) {
296 startServiceClient();
298 if (Conf::config
.useCache() && Conf::config
.useTwoWayCache()) {
302 printf("Database server started\n");
306 tval
.tv_sec
= timeout
.tv_sec
;
307 tval
.tv_usec
= timeout
.tv_usec
;
308 os::select(0, 0, 0, 0, &tval
);
310 //send signal to all the registered process..check they are alive
311 cleanupDeadProcs(sysdb
);
313 //TODO::if it fails to start 5 times, exit
314 if (isCacheReq
&& cachepid
!=0 && checkDead(cachepid
))
316 if (isSQLReq
&& sqlserverpid
!=0 && checkDead(sqlserverpid
))
317 startServiceClient();
319 if (logActiveProcs(sysdb
) != OK
) {srvStop
= 0; goto reloop
; }
320 os::kill(cachepid
, SIGTERM
);
321 os::kill(sqlserverpid
, SIGTERM
);
322 //if (recoverFlag) dumpData();
323 logFine(Conf::logger
, "Server Exiting");
324 printf("Server Exiting\n");
325 logFine(Conf::logger
, "Server Ended");
327 Conf::logger
.stopLogger();
328 session
->destroySystemDatabase();
335 //TODO::TAKE exclusive lock
336 sprintf(cmd
, "csqldump >%s/csql.db.chkpt.1",Conf::config
.getDbFile());
337 int ret
= system(cmd
);
338 if (ret
!= 0) return;
339 sprintf(cmd
, "rm -rf %s/csql.db.cur", Conf::config
.getDbFile());
340 if (ret
!= 0) return;
341 sprintf(cmd
, "mv %s/csql.db.chkpt.1 %s/csql.db.chkpt", Conf::config
.getDbFile());
342 if (ret
!= 0) return;