submitting patch from enterprise version
[csql.git] / src / tools / csqlserver.cxx
blob3484f831bac079b63b8d9dd603b8b1bd715f5dce
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
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. *
9 * *
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. *
14 * *
15 ***************************************************************************/
16 #include<os.h>
17 #include<CSql.h>
18 #include<SessionImpl.h>
19 #include<Debug.h>
20 #include<Process.h>
21 #include<Database.h>
22 #include<Transaction.h>
23 #include<Lock.h>
24 #include<CacheTableLoader.h>
25 char* version = "csql-linux-i686-2.0GA";
26 int srvStop =0;
27 pid_t sqlserverpid=0;
28 pid_t cachepid=0;
29 bool recoverFlag=false;
30 void dumpData();
31 SessionImpl *session = NULL;
32 static void sigTermHandler(int sig)
34 printf("Received signal %d\nStopping the server\n", sig);
35 srvStop = 1;
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]);
56 //srvStop = 1;
57 //return ErrSysFatal;
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;
71 info->init();
72 delete tm;
73 delete lm;
74 return OK;
77 DbRetVal cleanupDeadProcs(Database *sysdb)
79 DbRetVal rv = sysdb->getProcessTableMutex(false);
80 if (OK != rv)
82 printError(rv,"Unable to get process table mutex");
83 return rv;
85 pid_t pid;
86 pid = os::getpid();
87 pthread_t thrid = os::getthrid();
90 ThreadInfo* pInfo = sysdb->getThreadInfo(0);
91 int i=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);
97 pInfo++;
99 sysdb->releaseProcessTableMutex(false);
100 return OK;
104 DbRetVal logActiveProcs(Database *sysdb)
106 DbRetVal rv = sysdb->getProcessTableMutex(false);
107 if (OK != rv)
109 printError(rv,"Unable to get process table mutex");
110 return rv;
112 ThreadInfo* pInfo = sysdb->getThreadInfo(0);
113 int i=0, count =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_);
120 count++;
122 pInfo++;
124 sysdb->releaseProcessTableMutex(false);
125 if (count) return ErrSysInternal; else return OK;
127 void startCacheServer()
129 printf("Starting Cache Recv Server\n");
130 char execName[1024];
131 sprintf(execName, "%s/bin/csqlcacheserver", os::getenv("CSQL_INSTALL_ROOT"));
132 printf("filename is %s\n", execName);
133 cachepid = os::createProcess(execName, "csqlcacheserver");
134 if (cachepid != -1)
135 printf("Cache Recv Server Started pid=%d\n", cachepid);
136 return;
139 void startServiceClient()
141 printf("Starting Csql Network Daemon\n");
142 char execName[1024];
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);
148 return;
151 void printUsage()
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");
157 return;
159 int main(int argc, char **argv)
161 int c = 0, opt = 0;
162 while ((c = getopt(argc, argv, "cv?")) != EOF)
164 switch (c)
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
169 default: opt=10;
172 }//while options
174 if (opt == 10) {
175 printUsage();
176 return 0;
177 }else if (opt ==2) {
178 printf("%s\n",version);
179 return 0;
181 session = new SessionImpl();
182 DbRetVal rv = session->readConfigFile();
183 if (rv != OK)
185 printf("Unable to read the configuration file \n");
186 return 1;
188 os::signal(SIGINT, sigTermHandler);
189 os::signal(SIGTERM, sigTermHandler);
190 rv = Conf::logger.startLogger(Conf::config.getLogFile(), true);
191 if (rv != OK)
193 printf("Unable to start the logger\n");
194 return 2;
196 bool isInit = true;
197 logFine(Conf::logger, "Server Started");
198 int ret = session->initSystemDatabase();
199 if (0 != ret)
201 //printf(" System Database Initialization failed\n");
202 printf("Attaching to exising database\n");
203 isInit = false;
204 delete session;
205 session = new SessionImpl();
206 ret = session->open(DBAUSER, DBAPASS);
207 if (ret !=0) {
208 printf("Unable to attach to existing database\n");
209 return 3;
211 }else {
212 printf("System Database initialized\n");
215 bool end = false;
216 struct timeval timeout, tval;
217 timeout.tv_sec = 5;
218 timeout.tv_usec = 0;
219 Database* sysdb = session->getSystemDatabase();
220 recoverFlag = false;
221 if(isInit && Conf::config.useDurability())
223 char dbChkptFileName[1024];
224 char dbRedoFileName[1024];
225 char cmd[1024];
226 sprintf(dbChkptFileName, "%s/csql.db.chkpt", Conf::config.getDbFile());
227 if (FILE *file = fopen(dbChkptFileName, "r"))
229 fclose(file);
230 sprintf(cmd, "csql -X -s %s",dbChkptFileName);
231 int ret = system(cmd);
232 if (ret != 0) {
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"))
239 fclose(file);
240 int ret = system("redo -a");
241 if (ret != 0) {
242 printf("Recovery failed. Redo log file corrupted\n");
243 Conf::logger.stopLogger();
244 session->destroySystemDatabase();
245 delete session;
246 return 10;
248 //TODO::generate checkpoint file
249 sprintf(cmd, "csqldump -X > %s",dbChkptFileName);
250 ret = system(cmd);
251 if (ret != 0) {
252 printf("Unable to create checkpoint file\n");
253 Conf::logger.stopLogger();
254 session->destroySystemDatabase();
255 delete session;
256 return 11;
258 ret = unlink(dbRedoFileName);
259 if (ret != 0) {
260 printf("Unable to delete redo log file. Delete and restart the server\n");
261 Conf::logger.stopLogger();
262 session->destroySystemDatabase();
263 delete session;
264 return 11;
268 recoverFlag = true;
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");
273 if (ret != 0) {
274 printf("Cached Tables recovery failed %d\n", ret);
275 Conf::logger.stopLogger();
276 session->destroySystemDatabase();
277 delete session;
278 return 2;
280 printf("Cached Tables recovered\n");
281 } else {
282 printf("Cache mode is not set in csql.conf. Cannot recover\n");
283 Conf::logger.stopLogger();
284 session->destroySystemDatabase();
285 delete session;
286 return 1;
289 GlobalUniqueID UID;
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()) {
295 isSQLReq = true;
296 startServiceClient();
298 if (Conf::config.useCache() && Conf::config.useTwoWayCache()) {
299 isCacheReq = true;
300 startCacheServer();
302 printf("Database server started\n");
303 reloop:
304 while(!srvStop)
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))
315 startCacheServer();
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");
326 UID.destroy();
327 Conf::logger.stopLogger();
328 session->destroySystemDatabase();
329 delete session;
330 return 0;
332 void dumpData()
334 char cmd[1024];
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;
343 return;